mirror of
https://github.com/Combodo/iTop.git
synced 2026-05-25 02:02:17 +02:00
Merge branch 'support/3.0' into saas/3.0
This commit is contained in:
343
tests/php-unit-tests/legacy-tests/GroupByAndFunctions.php
Normal file
343
tests/php-unit-tests/legacy-tests/GroupByAndFunctions.php
Normal file
@@ -0,0 +1,343 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2013-2021 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*/
|
||||
|
||||
require_once ('../../../approot.inc.php');
|
||||
require_once(APPROOT.'application/application.inc.php');
|
||||
require_once(APPROOT.'application/itopwebpage.class.inc.php');
|
||||
require_once(APPROOT.'application/startup.inc.php');
|
||||
require_once(APPROOT.'application/loginwebpage.class.inc.php');
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Main program
|
||||
//
|
||||
LoginWebPage::DoLogin(true); // Check user rights and prompt if needed
|
||||
|
||||
|
||||
$sSubmit = utils::ReadParam('submit', '', false, 'raw_data');
|
||||
if ($sSubmit != 'Reset')
|
||||
{
|
||||
$sOQL = utils::ReadParam('OQL_Request', '', false, 'raw_data');
|
||||
}
|
||||
else
|
||||
{
|
||||
$sOQL = '';
|
||||
}
|
||||
$bError = false;
|
||||
$oP = new iTopWebPage('Database inconsistencies');
|
||||
$oP->set_base(utils::GetAbsoluteUrlAppRoot().'tests/');
|
||||
$oP->set_title('Grouping with functions');
|
||||
$oP->add('<div style="padding: 15px;"><h2>Grouping with functions</h2>');
|
||||
$oP->add('<div style="padding: 15px; background: #ddd;">');
|
||||
try
|
||||
{
|
||||
if (!empty($sOQL))
|
||||
{
|
||||
// Getting class attributes
|
||||
$oSearch = DBSearch::FromOQL($sOQL);
|
||||
$aSearches = $oSearch->GetSearches();
|
||||
if ($oSearch instanceof DBUnionSearch)
|
||||
{
|
||||
$sClass = $aSearches[0]->GetClassAlias();
|
||||
$sRealClass = $aSearches[0]->GetClass();
|
||||
}
|
||||
else
|
||||
{
|
||||
$sClass = $oSearch->GetClassAlias();
|
||||
$sRealClass = $oSearch->GetClass();
|
||||
}
|
||||
|
||||
$sGroupBy1 = utils::ReadParam('groupby_1', '');
|
||||
$sGroupBy2 = utils::ReadParam('groupby_2', '');
|
||||
$sOrderBy1 = utils::ReadParam('orderby_1', '');
|
||||
$sOrderBy2 = utils::ReadParam('orderby_2', '');
|
||||
|
||||
$sAttributesOptions1 = '';
|
||||
$sAttributesOptions2 = '';
|
||||
$sAttributesOptions3 = '';
|
||||
$sAttributesOptions4 = '';
|
||||
|
||||
foreach(array('_itop_sum_', '_itop_avg_', '_itop_min_', '_itop_max_', '_itop_count_', 'group1', 'group2') as $sAttCode)
|
||||
{
|
||||
$sAttributesOptions3 .= '<option value="'.$sAttCode.'" '.($sOrderBy1 == $sAttCode ? 'selected' : '').'>'.$sAttCode.'</option>';
|
||||
$sAttributesOptions4 .= '<option value="'.$sAttCode.'" '.($sOrderBy2 == $sAttCode ? 'selected' : '').'>'.$sAttCode.'</option>';
|
||||
}
|
||||
|
||||
foreach(MetaModel::ListAttributeDefs($sRealClass) as $sAttCode => $oAttDef)
|
||||
{
|
||||
// Skip this attribute if not defined in this table
|
||||
if ($oSearch instanceof DBUnionSearch)
|
||||
{
|
||||
foreach($aSearches as $oSubQuery)
|
||||
{
|
||||
$sSubClass = $oSubQuery->GetClass();
|
||||
if (!MetaModel::IsValidAttCode($sSubClass, $sAttCode))
|
||||
{
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
$sAttributesOptions1 .= '<option value="'.$sAttCode.'" '.($sGroupBy1 == $sAttCode ? 'selected' : '').'>'.$sAttCode.'</option>';
|
||||
$sAttributesOptions2 .= '<option value="'.$sAttCode.'" '.($sGroupBy2 == $sAttCode ? 'selected' : '').'>'.$sAttCode.'</option>';
|
||||
}
|
||||
|
||||
$iLimit = intval(utils::ReadParam('top', '0'));
|
||||
|
||||
$sInvOrder1 = utils::ReadParam('desc1', '');
|
||||
$sCheck1 = ($sInvOrder1 == 'on' ? 'checked' : '');
|
||||
|
||||
$sInvOrder2 = utils::ReadParam('desc2', '');
|
||||
$sCheck2 = ($sInvOrder2 == 'on' ? 'checked' : '');
|
||||
|
||||
$sFuncField = utils::ReadParam('funcfield', '');
|
||||
|
||||
$sFuncFieldOption = '';
|
||||
foreach(MetaModel::ListAttributeDefs($sRealClass) as $sAttCode => $oAttDef)
|
||||
{
|
||||
// Skip this attribute if not defined in this table
|
||||
if ($oSearch instanceof DBUnionSearch)
|
||||
{
|
||||
foreach($aSearches as $oSubQuery)
|
||||
{
|
||||
$sSubClass = $oSubQuery->GetClass();
|
||||
if (!MetaModel::IsValidAttCode($sSubClass, $sAttCode))
|
||||
{
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
switch (get_class($oAttDef))
|
||||
{
|
||||
case 'Integer':
|
||||
case 'AttributeDecimal':
|
||||
case 'AttributeDuration':
|
||||
case 'AttributeSubItem':
|
||||
case 'AttributePercentage':
|
||||
$sFuncFieldOption .= '<option value="'.$sAttCode.'" '.($sFuncField == $sAttCode ? 'selected' : '').'>'.$sAttCode.'</option>';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
$oP->p('<div class="header_message message_error">'.$e->getMessage().'</div>');
|
||||
$bError = true;
|
||||
}
|
||||
$oP->add("<div><form>");
|
||||
$oP->add("<input type=\"submit\" name=\"submit\" value=\"Reset\">\n");
|
||||
$oP->add("</form></div>");
|
||||
|
||||
$oP->add("<form>");
|
||||
|
||||
$oP->add(
|
||||
<<<EOF
|
||||
<div>
|
||||
<label>Search OQL:</label>
|
||||
<div>
|
||||
<textarea id='OQL_Request' name='OQL_Request' cols='60' rows='5'>$sOQL</textarea>
|
||||
</div>
|
||||
</div>
|
||||
EOF
|
||||
);
|
||||
|
||||
if (!empty($sOQL) && !$bError)
|
||||
{
|
||||
$oP->add(
|
||||
<<<EOF
|
||||
<div>
|
||||
<label>Group by:</label>
|
||||
<div>
|
||||
<select id="groupby_1" name="groupby_1">
|
||||
$sAttributesOptions1
|
||||
</select>
|
||||
<select id="groupby_2" name="groupby_2">
|
||||
<option></option>
|
||||
$sAttributesOptions2
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label>Order by:</label>
|
||||
<div>
|
||||
<select id="orderby_1" name="orderby_1">$sAttributesOptions3</select>
|
||||
<label>Inv order</label><input type="checkbox" name="desc1" $sCheck1/>
|
||||
</div>
|
||||
<div>
|
||||
<select id="orderby_2" name="orderby_2">
|
||||
<option></option>
|
||||
$sAttributesOptions4
|
||||
</select>
|
||||
<label>Inv order</label><input type="checkbox" name="desc2" $sCheck2/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label>Functions on:</label>
|
||||
<div>
|
||||
<select id="funcfield" name="funcfield">$sFuncFieldOption</select>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label>Top:</label>
|
||||
<div><input type="text" id="top" name="top" value="$iLimit"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
EOF
|
||||
);
|
||||
}
|
||||
|
||||
$oP->add("<input type=\"submit\" name=\"submit\" value=\"Search\">\n");
|
||||
|
||||
$oP->add("</form>");
|
||||
|
||||
$sSQL = '';
|
||||
|
||||
|
||||
if (empty($sOQL) || empty($sGroupBy1))
|
||||
{
|
||||
$oP->output();
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
$iLimitStart = 0;
|
||||
$aOrderBy = array();
|
||||
if (!empty($sOrderBy1))
|
||||
{
|
||||
$aOrderBy[$sOrderBy1] = ($sInvOrder1 != 'on');
|
||||
}
|
||||
if (!empty($sOrderBy2))
|
||||
{
|
||||
$aOrderBy[$sOrderBy2] = ($sInvOrder2 != 'on');
|
||||
}
|
||||
|
||||
$aGroupBy = array();
|
||||
$oExpr1 = Expression::FromOQL($sClass.'.'.$sGroupBy1);
|
||||
$aGroupBy["group1"] = $oExpr1;
|
||||
|
||||
if (!empty($sGroupBy2))
|
||||
{
|
||||
$oExpr2 = Expression::FromOQL($sClass.'.'.$sGroupBy2);
|
||||
$aGroupBy["group2"] = $oExpr2;
|
||||
}
|
||||
|
||||
$aArgs = array();
|
||||
|
||||
if (empty($sFuncField))
|
||||
{
|
||||
$aFunctions = array();
|
||||
}
|
||||
else
|
||||
{
|
||||
$oTimeExpr = Expression::FromOQL($sClass.'.'.$sFuncField);
|
||||
$oSumExpr = new FunctionExpression('SUM', array($oTimeExpr));
|
||||
$oAvgExpr = new FunctionExpression('AVG', array($oTimeExpr));
|
||||
$oMinExpr = new FunctionExpression('MIN', array($oTimeExpr));
|
||||
$oMaxExpr = new FunctionExpression('MAX', array($oTimeExpr));
|
||||
// Alias => Expression
|
||||
$aFunctions = array(
|
||||
'_itop_sum_' => $oSumExpr,
|
||||
'_itop_avg_' => $oAvgExpr,
|
||||
'_itop_min_' => $oMinExpr,
|
||||
'_itop_max_' => $oMaxExpr,
|
||||
);
|
||||
}
|
||||
|
||||
$sSQL = $oSearch->MakeGroupByQuery($aArgs, $aGroupBy, false, $aFunctions, $aOrderBy, $iLimit, $iLimitStart);
|
||||
|
||||
$aRes = CMDBSource::QueryToArray($sSQL);
|
||||
|
||||
// Display results
|
||||
if (!empty($aRes))
|
||||
{
|
||||
$oP->add('<div>');
|
||||
$oP->add('<table class="listResults">');
|
||||
$aLine = $aRes[0];
|
||||
$aCols = array();
|
||||
$oP->add('<tr>');
|
||||
foreach(array_keys($aLine) as $item)
|
||||
{
|
||||
if (!is_numeric($item))
|
||||
{
|
||||
$aCols[] = $item;
|
||||
$oP->add("<th>$item</th>");
|
||||
}
|
||||
}
|
||||
$oP->add('</tr>');
|
||||
|
||||
foreach($aRes as $aLine)
|
||||
{
|
||||
$oP->add('<tr>');
|
||||
foreach($aCols as $sCol)
|
||||
{
|
||||
$oP->add("<td>".$aLine[$sCol]."</td>");
|
||||
}
|
||||
$oP->add('</tr>');
|
||||
}
|
||||
|
||||
$oP->add('</table>');
|
||||
$oP->add('</div>');
|
||||
}
|
||||
else
|
||||
{
|
||||
$oP->add("<p>No Result</p>\n");
|
||||
}
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
$oP->p('<div class="header_message message_error">'.$e->getMessage().'</div>');
|
||||
$bError = true;
|
||||
}
|
||||
|
||||
$oP->add("<div class=\"header_message message_info\">$sSQL</div>\n");
|
||||
|
||||
$oP->output();
|
||||
|
||||
return;
|
||||
|
||||
/*
|
||||
echo "<pre>";
|
||||
$aClassSelection = MetaModel::GetClasses();
|
||||
foreach($aClassSelection as $sClass)
|
||||
{
|
||||
if (!MetaModel::HasTable($sClass))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
foreach(MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef)
|
||||
{
|
||||
// Skip this attribute if not defined in this table
|
||||
if (!MetaModel::IsAttributeOrigin($sClass, $sAttCode))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
switch (get_class($oAttDef))
|
||||
{
|
||||
case 'Integer':
|
||||
case 'AttributeDecimal':
|
||||
case 'AttributeDuration':
|
||||
case 'AttributeSubItem':
|
||||
case 'AttributePercentage':
|
||||
echo "$sClass:$sAttCode = ".get_class($oAttDef)."\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
1
tests/php-unit-tests/legacy-tests/README.md
Normal file
1
tests/php-unit-tests/legacy-tests/README.md
Normal file
@@ -0,0 +1 @@
|
||||
Tests in this folder have been written before the introduction of PHPUnit in iTop, they are not run by the CI.
|
||||
286
tests/php-unit-tests/legacy-tests/VerifyOQL.php
Normal file
286
tests/php-unit-tests/legacy-tests/VerifyOQL.php
Normal file
@@ -0,0 +1,286 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Copyright (C) 2013-2021 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*/
|
||||
|
||||
require_once('../../../approot.inc.php');
|
||||
require_once(APPROOT.'/application/application.inc.php');
|
||||
require_once(APPROOT.'/application/startup.inc.php');
|
||||
require_once(APPROOT.'/application/loginwebpage.class.inc.php');
|
||||
|
||||
LoginWebPage::DoLogin(); // Check user rights and prompt if needed
|
||||
ApplicationMenu::CheckMenuIdEnabled('RunQueriesMenu');
|
||||
|
||||
function ShowExamples($oP, $sExpression)
|
||||
{
|
||||
$bUsingExample = false;
|
||||
|
||||
$aExamples = array(
|
||||
'Pedagogic examples' => array(
|
||||
"Web applications" => "SELECT WebApplication",
|
||||
"Person having an 'A' in their name" => "SELECT Person AS B WHERE B.name LIKE '%A%'",
|
||||
"Servers having a name like dbserver1.demo.com or dbserver023.foo.fr" => "SELECT Server WHERE name REGEXP '^dbserver[0-9]+\\\\..+\\\\.[a-z]{2,3}$'",
|
||||
"Changes planned on new year's day" => "SELECT Change AS ch WHERE ch.start_date >= '2009-12-31' AND ch.end_date <= '2010-01-01'",
|
||||
"IPs in a range" => "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')",
|
||||
"Persons below a given root organization" => "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",
|
||||
),
|
||||
'Usefull examples' => array(
|
||||
"NW interfaces of equipment in production for customer 'Demo'" => "SELECT PhysicalInterface AS if JOIN DatacenterDevice AS dev ON if.connectableci_id = dev.id WHERE dev.status = 'production' AND dev.organization_name = 'Demo'",
|
||||
"My tickets" => "SELECT Ticket AS t WHERE t.agent_id = :current_contact_id",
|
||||
"People being owner of an active ticket" => "SELECT Person AS p JOIN UserRequest AS u ON u.agent_id = p.id WHERE u.status != 'closed'",
|
||||
"Contracts terminating in the next thirty days" => "SELECT Contract AS c WHERE c.end_date > NOW() AND c.end_date < DATE_ADD(NOW(), INTERVAL 30 DAY)",
|
||||
"Orphan tickets (opened one hour ago, still not assigned)" => "SELECT UserRequest AS u WHERE u.start_date < DATE_SUB(NOW(), INTERVAL 60 MINUTE) AND u.status = 'new'",
|
||||
"Long lasting incidents (duration > 8 hours)" => "SELECT UserRequest AS u WHERE u.close_date > DATE_ADD(u.start_date, INTERVAL 8 HOUR)",
|
||||
),
|
||||
);
|
||||
|
||||
$aDisplayData = array();
|
||||
$oAppContext = new ApplicationContext();
|
||||
$sContext = $oAppContext->GetForForm();
|
||||
foreach ($aExamples as $sTopic => $aQueries)
|
||||
{
|
||||
foreach ($aQueries as $sDescription => $sOql)
|
||||
{
|
||||
$sHighlight = '';
|
||||
$sDisable = '';
|
||||
if ($sOql == $sExpression)
|
||||
{
|
||||
// this one is currently being tested, highlight it
|
||||
$sHighlight = "background-color:yellow;";
|
||||
$sDisable = 'disabled';
|
||||
// and remember we are testing a query of the list
|
||||
$bUsingExample = true;
|
||||
}
|
||||
//$aDisplayData[$sTopic][] = array(
|
||||
$aDisplayData[Dict::S('UI:RunQuery:QueryExamples')][] = array(
|
||||
'desc' => "<div style=\"$sHighlight\">".htmlentities($sDescription, ENT_QUOTES, 'UTF-8')."</div>",
|
||||
'oql' => "<div style=\"$sHighlight\">".htmlentities($sOql, ENT_QUOTES, 'UTF-8')."</div>",
|
||||
'go' => "<form method=\"get\"><input type=\"hidden\" name=\"expression\" value=\"$sOql\"><input type=\"submit\" value=\"".Dict::S('UI:Button:Test')."\" $sDisable>$sContext</form>\n",
|
||||
);
|
||||
}
|
||||
}
|
||||
$aDisplayConfig = array();
|
||||
$aDisplayConfig['desc'] = array('label' => Dict::S('UI:RunQuery:HeaderPurpose'), 'description' => Dict::S('UI:RunQuery:HeaderPurpose+'));
|
||||
$aDisplayConfig['oql'] = array('label' => Dict::S('UI:RunQuery:HeaderOQLExpression'), 'description' => Dict::S('UI:RunQuery:HeaderOQLExpression+'));
|
||||
$aDisplayConfig['go'] = array('label' => '', 'description' => '');
|
||||
|
||||
foreach ($aDisplayData as $sTopic => $aQueriesDisplayData)
|
||||
{
|
||||
$bShowOpened = $bUsingExample;
|
||||
$oP->StartCollapsibleSection($sTopic, $bShowOpened);
|
||||
$oP->table($aDisplayConfig, $aQueriesDisplayData);
|
||||
$oP->EndCollapsibleSection();
|
||||
}
|
||||
}
|
||||
|
||||
$sOperation = utils::ReadParam('operation', 'menu');
|
||||
$oAppContext = new ApplicationContext();
|
||||
|
||||
$oP = new iTopWebPage(Dict::S('UI:RunQuery:Title'));
|
||||
$oP->SetBreadCrumbEntry('ui-tool-runquery', Dict::S('Menu:RunQueriesMenu'), Dict::S('Menu:RunQueriesMenu+'), '', 'fas fa-terminal', iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES);
|
||||
|
||||
// Main program
|
||||
$sExpression = utils::ReadParam('expression', '', false, 'raw_data');
|
||||
$sEncoding = utils::ReadParam('encoding', 'oql');
|
||||
|
||||
ShowExamples($oP, $sExpression);
|
||||
|
||||
try
|
||||
{
|
||||
if ($sEncoding == 'crypted')
|
||||
{
|
||||
// Translate $sExpression into a oql expression
|
||||
$sClearText = base64_decode($sExpression);
|
||||
echo "<strong>FYI: '$sClearText'</strong><br/>\n";
|
||||
$oFilter = DBObjectSearch::unserialize($sExpression);
|
||||
$sExpression = $oFilter->ToOQL();
|
||||
}
|
||||
|
||||
$oFilter = null;
|
||||
$aArgs = array();
|
||||
$sSyntaxError = null;
|
||||
|
||||
if (!empty($sExpression))
|
||||
{
|
||||
try
|
||||
{
|
||||
$oFilter = DBObjectSearch::FromOQL($sExpression);
|
||||
} catch (Exception $e)
|
||||
{
|
||||
if ($e instanceof OqlException)
|
||||
{
|
||||
$sSyntaxError = $e->getHtmlDesc();
|
||||
}
|
||||
else
|
||||
{
|
||||
$sSyntaxError = $e->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
if ($oFilter)
|
||||
{
|
||||
$aArgs = array();
|
||||
foreach ($oFilter->GetQueryParams() as $sParam => $foo)
|
||||
{
|
||||
$value = utils::ReadParam('arg_'.$sParam, null, true, 'raw_data');
|
||||
if (!is_null($value))
|
||||
{
|
||||
$aArgs[$sParam] = $value;
|
||||
}
|
||||
else
|
||||
{
|
||||
$aArgs[$sParam] = '';
|
||||
}
|
||||
}
|
||||
$oFilter->SetInternalParams($aArgs);
|
||||
}
|
||||
}
|
||||
|
||||
$oP->add("<form method=\"post\">\n");
|
||||
$oP->add(Dict::S('UI:RunQuery:ExpressionToEvaluate')."<br/>\n");
|
||||
$oP->add("<textarea cols=\"120\" rows=\"8\" id=\"expression\" name=\"expression\">".htmlentities($sExpression, ENT_QUOTES, 'UTF-8')."</textarea>\n");
|
||||
$oP->add_linked_script(utils::GetAbsoluteUrlAppRoot()."/js/jquery.hotkeys.js");
|
||||
$oP->add_ready_script(<<<EOF
|
||||
$("#expression").select();
|
||||
$("#expression").on("keydown", null, "ctrl+return", function() {
|
||||
$(this).closest("form").submit();
|
||||
});
|
||||
EOF
|
||||
);
|
||||
|
||||
if (count($aArgs) > 0)
|
||||
{
|
||||
$oP->add("<div class=\"wizContainer\">\n");
|
||||
$oP->add("<h3>Query arguments</h3>\n");
|
||||
foreach ($aArgs as $sParam => $sValue)
|
||||
{
|
||||
$oP->p("$sParam: <input type=\"string\" name=\"arg_$sParam\" value=\"$sValue\">\n");
|
||||
}
|
||||
$oP->add("</div>\n");
|
||||
}
|
||||
|
||||
$oP->add("<input type=\"submit\" value=\"".Dict::S('UI:Button:Evaluate')."\" title=\"".Dict::S('UI:Button:Evaluate:Title')."\">\n");
|
||||
$oP->add($oAppContext->GetForForm());
|
||||
$oP->add("</form>\n");
|
||||
|
||||
|
||||
if ($oFilter)
|
||||
{
|
||||
$oP->add("<h3>Query results</h3>\n");
|
||||
|
||||
$oResultBlock = new DisplayBlock($oFilter, 'list', false);
|
||||
$oResultBlock->Display($oP, 'runquery');
|
||||
|
||||
// Breadcrumb
|
||||
//$iCount = $oResultBlock->GetDisplayedCount();
|
||||
$sPageId = "ui-search-".$oFilter->GetClass();
|
||||
$sLabel = MetaModel::GetName($oFilter->GetClass());
|
||||
$aArgs = array();
|
||||
foreach (array_merge($_POST, $_GET) as $sKey => $value)
|
||||
{
|
||||
if (is_array($value))
|
||||
{
|
||||
$aItems = array();
|
||||
foreach ($value as $sItemKey => $sItemValue)
|
||||
{
|
||||
$aArgs[] = $sKey.'['.$sItemKey.']='.urlencode($sItemValue);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$aArgs[] = $sKey.'='.urlencode($value);
|
||||
}
|
||||
}
|
||||
$sUrl = utils::GetAbsoluteUrlAppRoot().'pages/run_query.php?'.implode('&', $aArgs);
|
||||
$oP->SetBreadCrumbEntry($sPageId, $sLabel, $oFilter->ToOQL(true), $sUrl, 'fas fa-terminal', iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES);
|
||||
|
||||
$oP->p('');
|
||||
$oP->StartCollapsibleSection(Dict::S('UI:RunQuery:MoreInfo'), false, 'runQuery');
|
||||
$oP->p('<pre>'.$oFilter->ToOQL().'</pre>');
|
||||
$oP->EndCollapsibleSection();
|
||||
|
||||
$aModifierProperties = MetaModel::MakeModifierProperties($oFilter);
|
||||
|
||||
$oP->StartCollapsibleSection('OQL Developed');
|
||||
$oSQLObjectQueryBuilder = new SQLObjectQueryBuilder($oFilter);
|
||||
$oBuild = new QueryBuilderContext($oFilter, $aModifierProperties);
|
||||
$oP->p('<pre>'.$oSQLObjectQueryBuilder->DebugOQLClassTree($oBuild).'</pre>');
|
||||
$oP->EndCollapsibleSection();
|
||||
|
||||
$oP->StartCollapsibleSection('SQL Count');
|
||||
$oSQLObjectQueryBuilder = new SQLObjectQueryBuilder($oFilter);
|
||||
$oBuild = new QueryBuilderContext($oFilter, $aModifierProperties);
|
||||
$oSQLQueryCount = $oSQLObjectQueryBuilder->BuildSQLQueryStruct(null, true, $aModifierProperties);
|
||||
$oP->p('<pre>'.$oSQLQueryCount->RenderSelect(array(), array(), 0, 0, true, true).'</pre>');
|
||||
$oP->EndCollapsibleSection();
|
||||
|
||||
$oP->StartCollapsibleSection('SQL');
|
||||
$oSQLObjectQueryBuilder = new SQLObjectQueryBuilder($oFilter);
|
||||
$oBuild = new QueryBuilderContext($oFilter, $aModifierProperties);
|
||||
$oSQLQuery = $oSQLObjectQueryBuilder->BuildSQLQueryStruct(null, false, $aModifierProperties);
|
||||
$oP->p('<pre>'.$oSQLQuery->RenderSelect(array(), array(), 10, 0, false, true).'</pre>');
|
||||
$oP->EndCollapsibleSection();
|
||||
|
||||
}
|
||||
elseif ($sSyntaxError)
|
||||
{
|
||||
if ($e instanceof OqlException)
|
||||
{
|
||||
$sWrongWord = $e->GetWrongWord();
|
||||
$aSuggestedWords = $e->GetSuggestions();
|
||||
if (count($aSuggestedWords) > 0)
|
||||
{
|
||||
$sSuggestedWord = OqlException::FindClosestString($sWrongWord, $aSuggestedWords);
|
||||
|
||||
if (strlen($sSuggestedWord) > 0)
|
||||
{
|
||||
$oP->p('<b>'.Dict::Format('UI:RunQuery:Error', $e->GetIssue().' <em>'.$sWrongWord).'</em></b>');
|
||||
$sBefore = substr($sExpression, 0, $e->GetColumn());
|
||||
$sAfter = substr($sExpression, $e->GetColumn() + strlen($sWrongWord));
|
||||
$sFixedExpression = $sBefore.$sSuggestedWord.$sAfter;
|
||||
$sFixedExpressionHtml = $sBefore.'<span style="background-color:yellow">'.$sSuggestedWord.'</span>'.$sAfter;
|
||||
$oP->p("Suggesting: $sFixedExpressionHtml");
|
||||
$oP->add('<button onClick="$(\'textarea[name=expression]\').val(\''.htmlentities(addslashes($sFixedExpression)).'\');">Use this query</button>');
|
||||
}
|
||||
else
|
||||
{
|
||||
$oP->p('<b>'.Dict::Format('UI:RunQuery:Error', $e->getHtmlDesc()).'</b>');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$oP->p('<b>'.Dict::Format('UI:RunQuery:Error', $e->getHtmlDesc()).'</b>');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$oP->p('<b>'.Dict::Format('UI:RunQuery:Error', $e->getMessage()).'</b>');
|
||||
}
|
||||
}
|
||||
} catch (Exception $e)
|
||||
{
|
||||
$oP->p('<b>'.Dict::Format('UI:RunQuery:Error', $e->getMessage()).'</b>');
|
||||
}
|
||||
|
||||
$oP->output();
|
||||
|
||||
862
tests/php-unit-tests/legacy-tests/benchmark.php
Normal file
862
tests/php-unit-tests/legacy-tests/benchmark.php
Normal file
@@ -0,0 +1,862 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2013-2021 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*/
|
||||
|
||||
require_once('../../../approot.inc.php');
|
||||
require_once(APPROOT.'/application/application.inc.php');
|
||||
require_once(APPROOT.'/application/wizardhelper.class.inc.php');
|
||||
require_once(APPROOT.'/application/startup.inc.php');
|
||||
require_once(APPROOT.'/application/loginwebpage.class.inc.php');
|
||||
require_once(APPROOT.'/application/utils.inc.php');
|
||||
require_once(APPROOT.'/setup/setuppage.class.inc.php');
|
||||
|
||||
//ini_set('memory_limit', '2048M');
|
||||
|
||||
class BenchmarkDataCreation
|
||||
{
|
||||
var $m_iIfByServer;
|
||||
var $m_iIfByNWDevice;
|
||||
var $m_aRequested;
|
||||
var $m_aPlanned;
|
||||
var $m_aCreatedByClass = array();
|
||||
var $m_aCreatedByDesc = array();
|
||||
|
||||
var $m_aStatsByClass = array();
|
||||
|
||||
/** @var \CMDBChange $m_oChange */
|
||||
var $m_oChange;
|
||||
public function __construct()
|
||||
{
|
||||
CMDBObject::SetTrackInfo('Benchmark setup');
|
||||
}
|
||||
|
||||
public function PlanStructure($iPlannedContacts, $iPlannedContracts)
|
||||
{
|
||||
$this->m_aRequested = array(
|
||||
'plannedcontacts' => $iPlannedContacts,
|
||||
'plannedcontracts' => $iPlannedContracts,
|
||||
);
|
||||
$this->m_aPlanned = array(
|
||||
'Contacts' => $iPlannedContacts,
|
||||
'Contracts' => $iPlannedContracts,
|
||||
'Documents' => $iPlannedContracts * 2,
|
||||
);
|
||||
}
|
||||
|
||||
public function PlanCis($iPlannedCIs)
|
||||
{
|
||||
$this->m_aRequested = array(
|
||||
'plannedcis' => $iPlannedCIs,
|
||||
);
|
||||
|
||||
$this->m_iIfByServer = 2;
|
||||
$this->m_iIfByNWDevice = 10;
|
||||
|
||||
$iServers = ceil($iPlannedCIs * 9 / 10);
|
||||
$iNWDevices = ceil($iPlannedCIs / 10);
|
||||
$iInterfaces = $iServers * $this->m_iIfByServer + $iNWDevices * $this->m_iIfByNWDevice;
|
||||
$iApplications = $iServers * 5;
|
||||
$iSolutions = ceil($iApplications / 2);
|
||||
$iProcesses = ceil($iSolutions / 2);
|
||||
|
||||
$this->m_aPlanned = array(
|
||||
'Network devices' => $iNWDevices,
|
||||
'Servers' => $iServers,
|
||||
'Interfaces' => $iInterfaces,
|
||||
'Application SW' => 2,
|
||||
'Applications' => $iApplications,
|
||||
'Solutions' => $iSolutions,
|
||||
'Processes' => $iProcesses,
|
||||
);
|
||||
}
|
||||
|
||||
public function PlanTickets($iPlannedTickets, $iBigTicketCis)
|
||||
{
|
||||
$this->m_aRequested = array(
|
||||
'plannedtickets' => $iPlannedTickets,
|
||||
'plannedbigticketcis' => $iBigTicketCis,
|
||||
);
|
||||
|
||||
$this->m_aPlanned = array(
|
||||
'Incidents' => ceil($iPlannedTickets / 2),
|
||||
'Changes' => ceil($iPlannedTickets / 2),
|
||||
'Big ticket: CIs' => $iBigTicketCis,
|
||||
);
|
||||
}
|
||||
|
||||
public function ShowPlans($oP)
|
||||
{
|
||||
$oP->add("<h2>Planned creations</h2>\n");
|
||||
$aPlanned = $this->m_aPlanned;
|
||||
$aForm = array();
|
||||
foreach ($aPlanned as $sKey => $iCount)
|
||||
{
|
||||
$aForm[] = array(
|
||||
'label' => $sKey,
|
||||
'input' => $iCount,
|
||||
);
|
||||
}
|
||||
$oP->form($aForm);
|
||||
}
|
||||
|
||||
public function ShowForm($oP, $sNextOperation)
|
||||
{
|
||||
$aRequested = $this->m_aRequested;
|
||||
$oP->add("<form method=\"post\" onSubmit=\"return DoSubmit('Loading data...', 10)\">\n");
|
||||
$oP->add("<input type=\"hidden\" name=\"operation\" value=\"$sNextOperation\">\n");
|
||||
foreach($this->m_aRequested as $sName => $sValue)
|
||||
{
|
||||
$oP->add("<input type=\"hidden\" name=\"$sName\" value=\"$sValue\">\n");
|
||||
}
|
||||
$oP->add("<button type=\"submit\">Next >></button>\n");
|
||||
$oP->add("</form>\n");
|
||||
}
|
||||
|
||||
protected function CreateObject($sClass, $aData, $sClassDesc = '')
|
||||
{
|
||||
$mu_t1 = MyHelpers::getmicrotime();
|
||||
|
||||
$oMyObject = MetaModel::NewObject($sClass);
|
||||
foreach($aData as $sProp => $value)
|
||||
{
|
||||
if (is_array($value))
|
||||
{
|
||||
// transform into a link set
|
||||
$sCSVSpec = implode('|', $value);
|
||||
$oAttDef = MetaModel::GetAttributeDef($sClass, $sProp);
|
||||
$value = $oAttDef->MakeValueFromString($sCSVSpec, $bLocalizedValue = false, $sSepItem = '|', $sSepAttribute = ';', $sSepValue = ':', $sAttributeQualifier = '"');
|
||||
}
|
||||
$oMyObject->Set($sProp, $value);
|
||||
}
|
||||
|
||||
$iId = $oMyObject->DBInsertNoReload();
|
||||
|
||||
$sClassId = "$sClass ($sClassDesc)";
|
||||
$this->m_aCreatedByDesc[$sClassId][] = $iId;
|
||||
$this->m_aCreatedByClass[$sClass][] = $iId;
|
||||
|
||||
$mu_t2 = MyHelpers::getmicrotime();
|
||||
$this->m_aStatsByClass[$sClass][] = $mu_t2 - $mu_t1;
|
||||
|
||||
return $iId;
|
||||
}
|
||||
|
||||
static $m_aClassIdCache = array();
|
||||
protected function GetClassIds($sClass)
|
||||
{
|
||||
if (!isset(self::$m_aClassIdCache[$sClass]))
|
||||
{
|
||||
// Load the cache now
|
||||
self::$m_aClassIdCache[$sClass] = array();
|
||||
|
||||
$oSet = new DBObjectSet(new DBObjectSearch($sClass));
|
||||
while($oObj = $oSet->Fetch())
|
||||
{
|
||||
self::$m_aClassIdCache[$sClass][] = $oObj->GetKey();
|
||||
}
|
||||
}
|
||||
return self::$m_aClassIdCache[$sClass];
|
||||
}
|
||||
|
||||
protected function RandomId($sClass, $sClassDesc = '')
|
||||
{
|
||||
$sClassId = "$sClass ($sClassDesc)";
|
||||
if (isset($this->m_aCreatedByDesc[$sClassId]))
|
||||
{
|
||||
return $this->m_aCreatedByDesc[$sClassId][array_rand($this->m_aCreatedByDesc[$sClassId])];
|
||||
}
|
||||
|
||||
$aIds = self::GetClassIds($sClass);
|
||||
return $aIds[array_rand($aIds)];
|
||||
}
|
||||
|
||||
static protected function FindId($sClass)
|
||||
{
|
||||
$oSet = new DBObjectSet(new DBObjectSearch($sClass));
|
||||
if ($oSet->Count() < 1)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
$oObj = $oSet->Fetch();
|
||||
return $oObj->GetKey();
|
||||
}
|
||||
|
||||
static protected function FindIdFromOQL($sOQL)
|
||||
{
|
||||
$oSet = new DBObjectSet(DBObjectSearch::FromOQL($sOQL));
|
||||
if ($oSet->Count() < 1)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
$oObj = $oSet->Fetch();
|
||||
return $oObj->GetKey();
|
||||
}
|
||||
|
||||
protected function my_array_rand($aData, $iCount)
|
||||
{
|
||||
if ($iCount == 0)
|
||||
{
|
||||
return array();
|
||||
}
|
||||
elseif ($iCount == 1)
|
||||
{
|
||||
// array_rand() for one item returns only the key
|
||||
$key = array_rand($aData);
|
||||
$aSample = array($key);
|
||||
}
|
||||
elseif ($iCount <= count($aData))
|
||||
{
|
||||
$aSample = array_rand($aData, $iCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
$aSample = array_merge(array_keys($aData), self::my_array_rand($aData, $iCount - count($aData)));
|
||||
}
|
||||
return $aSample;
|
||||
}
|
||||
|
||||
protected function CreateLinks($iFrom, $iCount, $sLinkClass, $sAttCodeFrom, $sAttCodeTo)
|
||||
{
|
||||
$oAttTo = MetaModel::GetAttributeDef($sLinkClass, $sAttCodeTo);
|
||||
$sToClass = $oAttTo->GetTargetClass();
|
||||
|
||||
$aTargets = self::GetClassIds($sToClass);
|
||||
$aSample = self::my_array_rand($aTargets, $iCount);
|
||||
|
||||
foreach($aSample as $key)
|
||||
{
|
||||
$aData = array(
|
||||
$sAttCodeFrom => $iFrom,
|
||||
$sAttCodeTo => $aTargets[$key],
|
||||
);
|
||||
$this->CreateObject($sLinkClass, $aData);
|
||||
}
|
||||
}
|
||||
|
||||
public function CreateStructure($oP)
|
||||
{
|
||||
$aClasses = MetaModel::GetClasses();
|
||||
$aActions = array('Read', 'Bulk Read', 'Delete', 'Bulk Delete', 'Modify', 'Bulk Modify');
|
||||
$aStdProfiles = array(2, 3, 4, 5, 6, 7, 8, 9);
|
||||
|
||||
////////////////////////////////////////
|
||||
// New specific profile, giving access to everything
|
||||
//
|
||||
$aData = array(
|
||||
'name' => 'Data guru',
|
||||
'description' => 'Could do anything, because everything is granted',
|
||||
);
|
||||
$iGuruProfile = $this->CreateObject('URP_Profiles', $aData);
|
||||
foreach($aClasses as $sClass)
|
||||
{
|
||||
foreach($aActions as $sAction)
|
||||
{
|
||||
$aData = array(
|
||||
'profileid' => $iGuruProfile,
|
||||
'class' => $sClass,
|
||||
'permission' => 'yes',
|
||||
'action' => $sAction,
|
||||
);
|
||||
$this->CreateObject('URP_ActionGrant', $aData);
|
||||
}
|
||||
}
|
||||
|
||||
// User login with super access rights
|
||||
//
|
||||
$aData = array(
|
||||
'org_id' => self::FindId('Organization'),
|
||||
'location_id' => self::FindId('Location'),
|
||||
'first_name' => 'Jesus',
|
||||
'name' => 'Deus',
|
||||
'email' => 'guru@combodo.com',
|
||||
);
|
||||
$iPerson = $this->CreateObject('Person', $aData);
|
||||
$aData = array(
|
||||
'contactid' => $iPerson,
|
||||
'login' => 'guru',
|
||||
'password' => 'guru',
|
||||
'language' => 'EN US',
|
||||
'profile_list' => array("profileid:$iGuruProfile;reason:he is the one"),
|
||||
);
|
||||
$iLogin = $this->CreateObject('UserLocal', $aData);
|
||||
|
||||
////////////////////////////////////////
|
||||
// User login having all std profiles
|
||||
//
|
||||
$aData = array(
|
||||
'org_id' => self::FindId('Organization'),
|
||||
'location_id' => self::FindId('Location'),
|
||||
'first_name' => 'Little ze',
|
||||
'name' => 'Foo',
|
||||
'email' => 'foo@combodo.com',
|
||||
);
|
||||
$iPerson = $this->CreateObject('Person', $aData);
|
||||
|
||||
$aProfileSet = array();
|
||||
foreach($aStdProfiles as $iProfileId)
|
||||
{
|
||||
$aProfileSet[] = "profileid:$iProfileId;reason:xxx";
|
||||
}
|
||||
$aData = array(
|
||||
'contactid' => $iPerson,
|
||||
'login' => 'foo',
|
||||
'password' => 'foo',
|
||||
'language' => 'EN US',
|
||||
'profile_list' => $aProfileSet,
|
||||
);
|
||||
$iLogin = $this->CreateObject('UserLocal', $aData);
|
||||
|
||||
/////////////////////////
|
||||
//
|
||||
// Organizations
|
||||
//
|
||||
$aData = array(
|
||||
'name' => 'Benchmark',
|
||||
);
|
||||
$iOrg = $this->CreateObject('Organization', $aData);
|
||||
|
||||
/////////////////////////
|
||||
//
|
||||
// Locations
|
||||
//
|
||||
$aData = array(
|
||||
'org_id' => $iOrg,
|
||||
'name' => 'Rio de Janeiro',
|
||||
);
|
||||
$iLoc = $this->CreateObject('Location', $aData);
|
||||
|
||||
/////////////////////////
|
||||
//
|
||||
// Teams
|
||||
//
|
||||
$aData = array(
|
||||
'org_id' => $iOrg,
|
||||
'location_id' => $iLoc,
|
||||
'name' => 'Fluminense',
|
||||
'email' => 'fluminense@combodo.com',
|
||||
);
|
||||
$iTeam = $this->CreateObject('Team', $aData);
|
||||
|
||||
/////////////////////////
|
||||
//
|
||||
// Persons
|
||||
//
|
||||
for($i = 0 ; $i < $this->m_aPlanned['Contacts'] ; $i++)
|
||||
{
|
||||
$aData = array(
|
||||
'org_id' => $iOrg,
|
||||
'location_id' => $iLoc,
|
||||
'first_name' => 'Joaõ',
|
||||
'name' => 'Ningem #'.$i,
|
||||
'email' => 'foo'.$i.'@nowhere.fr',
|
||||
);
|
||||
$iPerson = $this->CreateObject('Person', $aData);
|
||||
|
||||
// Contract/Infra
|
||||
//
|
||||
$aData = array(
|
||||
'contact_id' => $iPerson,
|
||||
'team_id' => $this->RandomId('Team'),
|
||||
);
|
||||
$this->CreateObject('lnkTeamToContact', $aData);
|
||||
}
|
||||
|
||||
/////////////////////////
|
||||
//
|
||||
// Services
|
||||
//
|
||||
$aData = array(
|
||||
'org_id' => $iOrg,
|
||||
'name' => 'My Service',
|
||||
);
|
||||
$iService = $this->CreateObject('Service', $aData);
|
||||
|
||||
/////////////////////////
|
||||
//
|
||||
// Service subcategories
|
||||
//
|
||||
$aData = array(
|
||||
'name' => 'My subcategory',
|
||||
'service_id' => $iService,
|
||||
);
|
||||
$iOrg = $this->CreateObject('ServiceSubcategory', $aData);
|
||||
|
||||
/////////////////////////
|
||||
//
|
||||
// Contracts
|
||||
//
|
||||
for($i = 0 ; $i < $this->m_aPlanned['Contracts'] ; $i++)
|
||||
{
|
||||
$aData = array(
|
||||
'name' => "Contract #$i",
|
||||
'description' => 'Created for benchmarking purposes',
|
||||
'org_id' => $this->RandomId('Organization'),
|
||||
'provider_id' => $this->RandomId('Organization'),
|
||||
'start_date' => '2009-12-25',
|
||||
'end_date' => '2019-08-01',
|
||||
'support_team_id' => $this->RandomId('Team'),
|
||||
);
|
||||
$iContract = $this->CreateObject('CustomerContract', $aData);
|
||||
|
||||
// Contract/Contact (10% of contacts)
|
||||
//
|
||||
$iContactCount = ceil($this->m_aPlanned['Contracts'] / 10);
|
||||
for($iLinked = 0 ; $iLinked < $iContactCount ; $iLinked++)
|
||||
{
|
||||
$aData = array(
|
||||
'contact_id' => $this->RandomId('Person'),
|
||||
'contract_id' => $iContract,
|
||||
'role' => 'role '.$iLinked,
|
||||
);
|
||||
$this->CreateObject('lnkContractToContact', $aData);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////
|
||||
//
|
||||
// Documents
|
||||
//
|
||||
$sMyDoc = '';
|
||||
for($i = 0 ; $i < 1000 ; $i++)
|
||||
{
|
||||
// 100 chars
|
||||
$sMyDoc .= "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678\n";
|
||||
}
|
||||
$oRefDoc = new ormDocument($sMyDoc, 'text/plain');
|
||||
|
||||
for($i = 0 ; $i < $this->m_aPlanned['Documents'] ; $i++)
|
||||
{
|
||||
$aData = array(
|
||||
'org_id' => $iOrg,
|
||||
'name' => "document$i",
|
||||
'contents' => $oRefDoc,
|
||||
);
|
||||
$this->CreateObject('FileDoc', $aData);
|
||||
}
|
||||
}
|
||||
|
||||
public function CreateCis($oP)
|
||||
{
|
||||
$iOrg = $this->FindIdFromOQL("SELECT Organization WHERE name = 'Benchmark'");
|
||||
$iLoc = $this->FindIdFromOQL("SELECT Location WHERE org_id = $iOrg");
|
||||
|
||||
/////////////////////////
|
||||
//
|
||||
// Servers
|
||||
//
|
||||
for($i = 0 ; $i < $this->m_aPlanned['Servers'] ; $i++)
|
||||
{
|
||||
$aData = array(
|
||||
'org_id' => $iOrg,
|
||||
'location_id' => $iLoc,
|
||||
'name' => 'server'.$i,
|
||||
'status' => 'production',
|
||||
);
|
||||
$iServer = $this->CreateObject('Server', $aData);
|
||||
|
||||
// Contract/Infra
|
||||
$this->CreateLinks($iServer, 1, 'lnkContractToCI', 'ci_id', 'contract_id');
|
||||
|
||||
// Interfaces
|
||||
for($iLinked = 0 ; $iLinked < $this->m_iIfByServer ; $iLinked++)
|
||||
{
|
||||
$aData = array(
|
||||
'name' => "eth$iLinked",
|
||||
'status' => 'implementation',
|
||||
'org_id' => $iOrg,
|
||||
'device_id' => $iServer,
|
||||
'status' => 'production',
|
||||
);
|
||||
$this->CreateObject('NetworkInterface', $aData, 'server if');
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////
|
||||
//
|
||||
// Network devices
|
||||
//
|
||||
for($i = 0 ; $i < $this->m_aPlanned['Network devices'] ; $i++)
|
||||
{
|
||||
$aData = array(
|
||||
'org_id' => $iOrg,
|
||||
'location_id' => $iLoc,
|
||||
'name' => 'equipment #'.$i,
|
||||
'status' => 'production',
|
||||
);
|
||||
$iNWDevice = $this->CreateObject('NetworkDevice', $aData);
|
||||
|
||||
// Contract/Infra
|
||||
$this->CreateLinks($iNWDevice, 1, 'lnkContractToCI', 'ci_id', 'contract_id');
|
||||
|
||||
// Interfaces
|
||||
//
|
||||
for($iLinked = 0 ; $iLinked < $this->m_iIfByNWDevice ; $iLinked++)
|
||||
{
|
||||
$aData = array(
|
||||
'name' => "eth$iLinked",
|
||||
'status' => 'implementation',
|
||||
'org_id' => $iOrg,
|
||||
'device_id' => $iNWDevice,
|
||||
'connected_if' => $this->RandomId('NetworkInterface', 'server if'),
|
||||
'status' => 'production',
|
||||
);
|
||||
$this->CreateObject('NetworkInterface', $aData, 'equipment if');
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////
|
||||
//
|
||||
// Application Software
|
||||
//
|
||||
for($i = 0 ; $i < $this->m_aPlanned['Application SW'] ; $i++)
|
||||
{
|
||||
$aData = array(
|
||||
'name' => 'Software #'.$i,
|
||||
);
|
||||
$iNWDevice = $this->CreateObject('Application', $aData);
|
||||
}
|
||||
|
||||
/////////////////////////
|
||||
//
|
||||
// Applications
|
||||
//
|
||||
for($i = 0 ; $i < $this->m_aPlanned['Applications'] ; $i++)
|
||||
{
|
||||
$aData = array(
|
||||
'org_id' => $iOrg,
|
||||
'device_id' => $this->RandomId('Server'),
|
||||
'software_id' => $this->RandomId('Application'),
|
||||
'name' => 'Application #'.$i,
|
||||
'status' => 'production',
|
||||
);
|
||||
$iAppInstance = $this->CreateObject('ApplicationInstance', $aData);
|
||||
|
||||
// Contract/Infra
|
||||
$this->CreateLinks($iAppInstance, 1, 'lnkContractToCI', 'ci_id', 'contract_id');
|
||||
}
|
||||
|
||||
/////////////////////////
|
||||
//
|
||||
// Application Solution
|
||||
//
|
||||
for($i = 0 ; $i < $this->m_aPlanned['Solutions'] ; $i++)
|
||||
{
|
||||
$aData = array(
|
||||
'org_id' => $iOrg,
|
||||
'name' => 'Solution #'.$i,
|
||||
'status' => 'production',
|
||||
);
|
||||
$iAppSolution = $this->CreateObject('ApplicationSolution', $aData);
|
||||
|
||||
// Contract/Infra
|
||||
$this->CreateLinks($iAppSolution, 1, 'lnkContractToCI', 'ci_id', 'contract_id');
|
||||
}
|
||||
|
||||
/////////////////////////
|
||||
//
|
||||
// Business Process
|
||||
//
|
||||
for($i = 0 ; $i < $this->m_aPlanned['Processes'] ; $i++)
|
||||
{
|
||||
$aData = array(
|
||||
'org_id' => $iOrg,
|
||||
'name' => 'Process #'.$i,
|
||||
'status' => 'production',
|
||||
);
|
||||
$iProcess = $this->CreateObject('BusinessProcess', $aData);
|
||||
|
||||
// Contract/Infra
|
||||
$this->CreateLinks($iProcess, 1, 'lnkContractToCI', 'ci_id', 'contract_id');
|
||||
}
|
||||
}
|
||||
|
||||
public function CreateTickets($oP)
|
||||
{
|
||||
$iOrg = $this->FindIdFromOQL("SELECT Organization WHERE name = 'Benchmark'");
|
||||
$iLoc = $this->FindIdFromOQL("SELECT Location WHERE org_id = $iOrg");
|
||||
|
||||
/////////////////////////
|
||||
//
|
||||
// Incident Tickets
|
||||
//
|
||||
for($i = 0 ; $i < $this->m_aPlanned['Incidents'] ; $i++)
|
||||
{
|
||||
$aData = array(
|
||||
'org_id' => $iOrg,
|
||||
'caller_id' => $this->RandomId('Person'),
|
||||
'workgroup_id' => $this->RandomId('Team'),
|
||||
'agent_id' => $this->RandomId('Person'),
|
||||
'service_id' => $this->RandomId('Service'),
|
||||
'servicesubcategory_id' => $this->RandomId('ServiceSubcategory'),
|
||||
'title' => 'Incident #'.$i,
|
||||
'description' => 'O que aconteceu?',
|
||||
'ticket_log' => 'Testing...',
|
||||
);
|
||||
$iTicket = $this->CreateObject('Incident', $aData);
|
||||
|
||||
// Incident/Infra
|
||||
$iInfraCount = rand(1, 6);
|
||||
$this->CreateLinks($iTicket, $iInfraCount, 'lnkTicketToCI', 'ticket_id', 'ci_id');
|
||||
|
||||
// Incident/Infra
|
||||
$iContactCount = rand(1, 6);
|
||||
$this->CreateLinks($iTicket, $iContactCount, 'lnkTicketToContact', 'ticket_id', 'contact_id');
|
||||
}
|
||||
|
||||
/////////////////////////
|
||||
//
|
||||
// Big Ticket
|
||||
//
|
||||
$aData = array(
|
||||
'org_id' => $iOrg,
|
||||
'caller_id' => $this->RandomId('Person'),
|
||||
'workgroup_id' => $this->RandomId('Team'),
|
||||
'agent_id' => $this->RandomId('Person'),
|
||||
'service_id' => $this->RandomId('Service'),
|
||||
'servicesubcategory_id' => $this->RandomId('ServiceSubcategory'),
|
||||
'title' => 'Big ticket',
|
||||
'description' => 'O que aconteceu?',
|
||||
'ticket_log' => 'Testing...',
|
||||
);
|
||||
$iTicket = $this->CreateObject('Incident', $aData);
|
||||
|
||||
// Incident/Infra
|
||||
$iInfraCount = $this->m_aPlanned['Big ticket: CIs'];
|
||||
$this->CreateLinks($iTicket, $iInfraCount, 'lnkTicketToCI', 'ticket_id', 'ci_id');
|
||||
|
||||
// Incident/Infra
|
||||
$iContactCount = rand(1, 6);
|
||||
$this->CreateLinks($iTicket, $iContactCount, 'lnkTicketToContact', 'ticket_id', 'contact_id');
|
||||
|
||||
/////////////////////////
|
||||
//
|
||||
// Change Tickets
|
||||
//
|
||||
for($i = 0 ; $i < $this->m_aPlanned['Changes'] ; $i++)
|
||||
{
|
||||
$aData = array(
|
||||
'org_id' => $iOrg,
|
||||
'requestor_id' => $this->RandomId('Person'),
|
||||
'workgroup_id' => $this->RandomId('Team'),
|
||||
'agent_id' => $this->RandomId('Person'),
|
||||
'supervisor_group_id' => $this->RandomId('Team'),
|
||||
'supervisor_id' => $this->RandomId('Person'),
|
||||
'manager_group_id' => $this->RandomId('Team'),
|
||||
'manager_id' => $this->RandomId('Person'),
|
||||
'title' => 'change #'.$i,
|
||||
'description' => "Let's do something there",
|
||||
);
|
||||
$iTicket = $this->CreateObject('NormalChange', $aData);
|
||||
|
||||
// Incident/Infra
|
||||
$iInfraCount = rand(1, 6);
|
||||
$this->CreateLinks($iTicket, $iInfraCount, 'lnkTicketToCI', 'ticket_id', 'ci_id');
|
||||
|
||||
// Incident/Infra
|
||||
$iContactCount = rand(1, 6);
|
||||
$this->CreateLinks($iTicket, $iContactCount, 'lnkTicketToContact', 'ticket_id', 'contact_id');
|
||||
}
|
||||
}
|
||||
|
||||
public function MakeFeedback($oP)
|
||||
{
|
||||
foreach($this->m_aCreatedByClass as $sClass => $aClassIds)
|
||||
{
|
||||
$iSample = reset($aClassIds);
|
||||
$sSample = "<a href=\"".utils::GetAbsoluteUrlAppRoot()."pages/UI.php?operation=details&class=$sClass&id=$iSample\">sample</a>";
|
||||
|
||||
$iDuration = number_format(array_sum($this->m_aStatsByClass[$sClass]), 3);
|
||||
$fDurationMin = number_format(min($this->m_aStatsByClass[$sClass]), 3);
|
||||
$fDurationMax = number_format(max($this->m_aStatsByClass[$sClass]), 3);
|
||||
$fDurationAverage = number_format(array_sum($this->m_aStatsByClass[$sClass]) / count($this->m_aStatsByClass[$sClass]), 3);
|
||||
|
||||
$oP->add("<ul>");
|
||||
$oP->add("<li>");
|
||||
$oP->add("$sClass: ".count($this->m_aStatsByClass[$sClass])." - $sSample<br/>");
|
||||
$oP->add("Duration: $fDurationMin => $fDurationMax; Avg:$fDurationAverage; Total: $iDuration");
|
||||
$oP->add("</li>");
|
||||
$oP->add("</ul>");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ask the user what are the settings for the data load
|
||||
*/
|
||||
function DisplayStep1(SetupPage $oP)
|
||||
{
|
||||
$sNextOperation = 'step2';
|
||||
$oP->add("<h1>iTop benchmarking</h1>\n");
|
||||
|
||||
$oP->add("<form method=\"post\" onSubmit=\"return DoSubmit('Evaluating real plans...', 10)\">\n");
|
||||
$oP->add("<fieldset><legend>Data load configuration</legend>\n");
|
||||
$aForm = array();
|
||||
$aForm[] = array(
|
||||
'label' => "Contacts:",
|
||||
'input' => "<input id=\"from\" type=\"text\" name=\"plannedcontacts\" value=\"100\">",
|
||||
'help' => '',
|
||||
);
|
||||
$aForm[] = array(
|
||||
'label' => "Contracts:",
|
||||
'input' => "<input id=\"from\" type=\"text\" name=\"plannedcontracts\" value=\"10\">",
|
||||
'help' => '',
|
||||
);
|
||||
$oP->form($aForm);
|
||||
$oP->add("</fieldset>\n");
|
||||
$oP->add("<input type=\"hidden\" name=\"operation\" value=\"create_structure\">\n");
|
||||
$oP->add("<button type=\"submit\">Next >></button>\n");
|
||||
$oP->add("</form>\n");
|
||||
|
||||
$oP->add("<form method=\"post\" onSubmit=\"return DoSubmit('Evaluating real plans...', 10)\">\n");
|
||||
$oP->add("<fieldset><legend>Data load configuration</legend>\n");
|
||||
$aForm = array();
|
||||
$aForm[] = array(
|
||||
'label' => "Main CIs:",
|
||||
'input' => "<input id=\"to\" type=\"text\" name=\"plannedcis\" value=\"70\">",
|
||||
'help' => ' exclude interfaces, subnets or any other type of secondary CI',
|
||||
);
|
||||
$oP->form($aForm);
|
||||
$oP->add("</fieldset>\n");
|
||||
$oP->add("<input type=\"hidden\" name=\"operation\" value=\"create_cis\">\n");
|
||||
$oP->add("<button type=\"submit\">Next >></button>\n");
|
||||
$oP->add("</form>\n");
|
||||
|
||||
$oP->add("<form method=\"post\" onSubmit=\"return DoSubmit('Evaluating real plans...', 10)\">\n");
|
||||
$oP->add("<fieldset><legend>Data load configuration</legend>\n");
|
||||
$aForm = array();
|
||||
$aForm[] = array(
|
||||
'label' => "Tickets:",
|
||||
'input' => "<input id=\"to\" type=\"text\" name=\"plannedtickets\" value=\"200\">",
|
||||
'help' => ' 50% incidents, 50% changes',
|
||||
);
|
||||
$aForm[] = array(
|
||||
'label' => "CIs for the big ticket:",
|
||||
'input' => "<input id=\"to\" type=\"text\" name=\"plannedbigticketcis\" value=\"200\">",
|
||||
'help' => 'Number of CI for the single big ticket',
|
||||
);
|
||||
$oP->form($aForm);
|
||||
$oP->add("</fieldset>\n");
|
||||
$oP->add("<input type=\"hidden\" name=\"operation\" value=\"create_tickets\">\n");
|
||||
$oP->add("<button type=\"submit\">Next >></button>\n");
|
||||
$oP->add("</form>\n");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Main program
|
||||
*/
|
||||
|
||||
LoginWebPage::DoLogin(); // Check user rights and prompt if needed
|
||||
|
||||
$sOperation = Utils::ReadParam('operation', 'step1');
|
||||
$oP = new SetupPage('iTop benchmark utility');
|
||||
|
||||
ExecutionKPI::EnableDuration();
|
||||
$oKPI = new ExecutionKPI();
|
||||
|
||||
try
|
||||
{
|
||||
switch($sOperation)
|
||||
{
|
||||
case 'step1':
|
||||
DisplayStep1($oP);
|
||||
break;
|
||||
|
||||
case 'create_structure':
|
||||
$oP->no_cache();
|
||||
$oP->add_xframe_options('DENY');
|
||||
$iPlannedContacts = Utils::ReadParam('plannedcontacts');
|
||||
$iPlannedContracts = Utils::ReadParam('plannedcontracts');
|
||||
|
||||
$oDataCreation = new BenchmarkDataCreation();
|
||||
$oDataCreation->PlanStructure($iPlannedContacts, $iPlannedContracts);
|
||||
$oDataCreation->ShowPlans($oP);
|
||||
$oDataCreation->ShowForm($oP, 'create_structure_go');
|
||||
break;
|
||||
|
||||
case 'create_structure_go':
|
||||
$oP->no_cache();
|
||||
$iPlannedContacts = Utils::ReadParam('plannedcontacts');
|
||||
$iPlannedContracts = Utils::ReadParam('plannedcontracts');
|
||||
|
||||
$oDataCreation = new BenchmarkDataCreation();
|
||||
$oDataCreation->PlanStructure($iPlannedContacts, $iPlannedContracts);
|
||||
$oDataCreation->CreateStructure($oP);
|
||||
$oDataCreation->MakeFeedback($oP);
|
||||
break;
|
||||
|
||||
case 'create_cis':
|
||||
$oP->no_cache();
|
||||
$iPlannedCIs = Utils::ReadParam('plannedcis');
|
||||
|
||||
$oDataCreation = new BenchmarkDataCreation();
|
||||
$oDataCreation->PlanCis($iPlannedCIs);
|
||||
$oDataCreation->ShowPlans($oP);
|
||||
$oDataCreation->ShowForm($oP, 'create_cis_go');
|
||||
break;
|
||||
|
||||
case 'create_cis_go':
|
||||
$oP->no_cache();
|
||||
$iPlannedCIs = Utils::ReadParam('plannedcis');
|
||||
|
||||
$oDataCreation = new BenchmarkDataCreation();
|
||||
$oDataCreation->PlanCis($iPlannedCIs);
|
||||
$oDataCreation->CreateCis($oP);
|
||||
$oDataCreation->MakeFeedback($oP);
|
||||
break;
|
||||
|
||||
case 'create_tickets':
|
||||
$oP->no_cache();
|
||||
$iPlannedTickets = Utils::ReadParam('plannedtickets');
|
||||
$iBigTicketCis = Utils::ReadParam('plannedbigticketcis');
|
||||
|
||||
$oDataCreation = new BenchmarkDataCreation();
|
||||
$oDataCreation->PlanTickets($iPlannedTickets, $iBigTicketCis);
|
||||
$oDataCreation->ShowPlans($oP);
|
||||
$oDataCreation->ShowForm($oP, 'create_tickets_go');
|
||||
break;
|
||||
|
||||
case 'create_tickets_go':
|
||||
$oP->no_cache();
|
||||
$iPlannedTickets = Utils::ReadParam('plannedtickets');
|
||||
$iBigTicketCis = Utils::ReadParam('plannedbigticketcis');
|
||||
|
||||
$oDataCreation = new BenchmarkDataCreation();
|
||||
$oDataCreation->PlanTickets($iPlannedTickets, $iBigTicketCis);
|
||||
$oDataCreation->CreateTickets($oP);
|
||||
$oDataCreation->MakeFeedback($oP);
|
||||
break;
|
||||
|
||||
default:
|
||||
$oP->error("Error: unsupported operation '$sOperation'");
|
||||
}
|
||||
}
|
||||
catch(ZZException $e)
|
||||
{
|
||||
$oP->error("Error: '".$e->getMessage()."'");
|
||||
}
|
||||
catch(ZZCoreException $e)
|
||||
{
|
||||
$oP->error("Error: '".$e->getHtmlDesc()."'");
|
||||
}
|
||||
$oKPI->ComputeAndReport('Total execution');
|
||||
//DBSearch::RecordQueryTrace();
|
||||
$oP->output();
|
||||
?>
|
||||
146
tests/php-unit-tests/legacy-tests/build_test_oql.php
Normal file
146
tests/php-unit-tests/legacy-tests/build_test_oql.php
Normal file
@@ -0,0 +1,146 @@
|
||||
<?php
|
||||
// Copyright (c) 2010-2021 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// iTop is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
//
|
||||
|
||||
/**
|
||||
* Date: 06/10/2017
|
||||
*/
|
||||
|
||||
|
||||
require_once('../../../approot.inc.php');
|
||||
require_once(APPROOT.'application/startup.inc.php');
|
||||
|
||||
\LoginWebPage::DoLogin(true);
|
||||
|
||||
$sOQLFile = APPROOT.'log/oql_records.txt';
|
||||
$sTestFile = APPROOT.'tests/core/oql_records.php';
|
||||
|
||||
$oTestHandle = @fopen($sTestFile, "w");
|
||||
|
||||
@fwrite($oTestHandle, "<?php\n\n");
|
||||
|
||||
$aFoundOQLs = array();
|
||||
$iCount = 0;
|
||||
$iRead = 0;
|
||||
|
||||
$oOQLHandle = @fopen($sOQLFile, "r");
|
||||
if ($oOQLHandle) {
|
||||
while (($sBuffer = fgets($oOQLHandle)) !== false) {
|
||||
$iRead++;
|
||||
$aRecord = unserialize($sBuffer);
|
||||
|
||||
$sOQL = $aRecord['oql'];
|
||||
|
||||
$sChecksum = md5($sBuffer);
|
||||
if (isset($aFoundOQLs[$sChecksum])) { continue; }
|
||||
$aFoundOQLs[$sChecksum] = true;
|
||||
|
||||
$iCount++;
|
||||
$sOrderBy = ConvertArray($aRecord['order_by']);
|
||||
$sAttToLoad = ConvertArray($aRecord['att_to_load']);
|
||||
$iLimitCount = $aRecord['limit_count'];
|
||||
$iLimitStart = $aRecord['limit_start'];
|
||||
|
||||
// $sOQL, $aOrderBy, $aArgs, $aAttToLoad, $aExtendedDataSpec, $iLimitCount, $iLimitStart
|
||||
|
||||
$sLine = "\$aData[\"SELECT $iCount\"] = array(\"$sOQL\", $sOrderBy, array(), $sAttToLoad, array(), $iLimitCount, $iLimitStart);\n";
|
||||
@fwrite($oTestHandle, $sLine);
|
||||
}
|
||||
if (!feof($oOQLHandle)) {
|
||||
echo "Erreur: fgets() a échoué\n";
|
||||
}
|
||||
@fclose($oOQLHandle);
|
||||
}
|
||||
@fwrite($oTestHandle, "\n");
|
||||
|
||||
@fclose($oTestHandle);
|
||||
|
||||
echo "File '$sTestFile' generated with $iCount entries (from $iRead captured OQL).\n";
|
||||
|
||||
|
||||
/// Group by
|
||||
|
||||
|
||||
$sOQLFile = APPROOT.'log/oql_group_by_records.txt';
|
||||
$sTestFile = APPROOT.'tests/core/oql_group_by_records.php';
|
||||
|
||||
$oTestHandle = @fopen($sTestFile, "w");
|
||||
|
||||
@fwrite($oTestHandle, "<?php\n\n");
|
||||
|
||||
$aFoundOQLs = array();
|
||||
$iCount = 1000;
|
||||
$iRead = 0;
|
||||
|
||||
$oOQLHandle = @fopen($sOQLFile, "r");
|
||||
if ($oOQLHandle) {
|
||||
while (($sBuffer = fgets($oOQLHandle)) !== false) {
|
||||
$iRead++;
|
||||
$aRecord = unserialize($sBuffer);
|
||||
|
||||
$sOQL = $aRecord['oql'];
|
||||
|
||||
$sChecksum = md5($sBuffer);
|
||||
if (isset($aFoundOQLs[$sChecksum])) { continue; }
|
||||
$aFoundOQLs[$sChecksum] = true;
|
||||
|
||||
$iCount++;
|
||||
$sOrderBy = ConvertArray($aRecord['order_by']);
|
||||
$sGroupByExpr = ConvertArray($aRecord['group_by_expr']);
|
||||
$sSelectExpr = ConvertArray($aRecord['select_expr']);
|
||||
if ($aRecord['exclude_null_values'])
|
||||
{
|
||||
$bExcludeNullValues = 'true';
|
||||
}
|
||||
else
|
||||
{
|
||||
$bExcludeNullValues = 'false';
|
||||
}
|
||||
$iLimitCount = $aRecord['limit_count'];
|
||||
$iLimitStart = $aRecord['limit_start'];
|
||||
|
||||
// $sOQL, $aArgs, $aGroupByExpr, $bExcludeNullValues, $aSelectExpr, $aOrderBy, $iLimitCount, $iLimitStart
|
||||
|
||||
$sLine = "\$aData[\"SELECT $iCount\"] = array(\"$sOQL\", array(), $sGroupByExpr, $bExcludeNullValues, $sSelectExpr, $sOrderBy, $iLimitCount, $iLimitStart);\n";
|
||||
@fwrite($oTestHandle, $sLine);
|
||||
}
|
||||
if (!feof($oOQLHandle)) {
|
||||
echo "Erreur: fgets() a échoué\n";
|
||||
}
|
||||
@fclose($oOQLHandle);
|
||||
}
|
||||
@fwrite($oTestHandle, "\n");
|
||||
|
||||
@fclose($oTestHandle);
|
||||
|
||||
echo "<br>File '$sTestFile' generated with ".($iCount-1000)." entries (from $iRead captured OQL).\n";
|
||||
|
||||
function ConvertArray($aArray)
|
||||
{
|
||||
if (is_null($aArray))
|
||||
{
|
||||
return 'null';
|
||||
}
|
||||
|
||||
if (empty($aArray))
|
||||
{
|
||||
return 'array()';
|
||||
}
|
||||
|
||||
return 'unserialize(\''.str_replace("'", "\\'",serialize($aArray)).'\')';
|
||||
}
|
||||
38
tests/php-unit-tests/legacy-tests/config-test-farm.php
Normal file
38
tests/php-unit-tests/legacy-tests/config-test-farm.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
//
|
||||
// phpMyORM configuration file
|
||||
//
|
||||
// To be manually edited (or generated by the configuration wizard)
|
||||
//
|
||||
// The file is used in MetaModel::LoadConfig() which does all the necessary initialization job
|
||||
//
|
||||
|
||||
$MySettings = array(
|
||||
'db_host' => 'localhost',
|
||||
'db_user' => 'root',
|
||||
'db_pwd' => '',
|
||||
'db_name' => 'TestFarm',
|
||||
'db_subname' => '', // use it to differentiate two applications instances running on the same DB
|
||||
);
|
||||
|
||||
// Modules: file names should be specified as a absolute paths
|
||||
|
||||
$MyModules = array(
|
||||
'application' => array (
|
||||
// '../core/event.class.inc.php',
|
||||
// '../core/action.class.inc.php',
|
||||
// '../core/trigger.class.inc.php',
|
||||
// to be continued...
|
||||
),
|
||||
'business' => array (
|
||||
'../business/test_farm.class.inc.php',
|
||||
// to be continued...
|
||||
),
|
||||
'addons' => array (
|
||||
//'user rights' => '/addons/userrights/userrightsnull.class.inc.php', // or userrightsmatrix.class.inc.php
|
||||
// other modules to come later
|
||||
)
|
||||
);
|
||||
|
||||
?>
|
||||
104
tests/php-unit-tests/legacy-tests/display_cache_content.php
Normal file
104
tests/php-unit-tests/legacy-tests/display_cache_content.php
Normal file
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2013-2021 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*/
|
||||
|
||||
/**
|
||||
* Date: 06/10/2017
|
||||
*/
|
||||
|
||||
require_once('../../../approot.inc.php');
|
||||
require_once(APPROOT.'application/startup.inc.php');
|
||||
|
||||
|
||||
$sEnvironment = MetaModel::GetEnvironmentId();
|
||||
$aEntries = array();
|
||||
$aCacheUserData = apc_cache_info_compat();
|
||||
if (is_array($aCacheUserData) && isset($aCacheUserData['cache_list']))
|
||||
{
|
||||
$sPrefix = 'itop-'.$sEnvironment.'-query-cache-';
|
||||
|
||||
foreach($aCacheUserData['cache_list'] as $i => $aEntry)
|
||||
{
|
||||
$sEntryKey = array_key_exists('info', $aEntry) ? $aEntry['info'] : $aEntry['key'];
|
||||
if (strpos($sEntryKey, $sPrefix) === 0)
|
||||
{
|
||||
$aEntries[] = $sEntryKey;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
echo "<pre>";
|
||||
|
||||
if (empty($aEntries))
|
||||
{
|
||||
echo "No Data";
|
||||
return;
|
||||
}
|
||||
|
||||
$sKey = $aEntries[0];
|
||||
$result = apc_fetch($sKey);
|
||||
if (!is_object($result))
|
||||
{
|
||||
return;
|
||||
}
|
||||
$oSQLQuery = $result;
|
||||
|
||||
echo "NB Tables before;NB Tables after;";
|
||||
foreach($oSQLQuery->m_aContextData as $sField => $oValue)
|
||||
{
|
||||
echo $sField.';';
|
||||
}
|
||||
echo "\n";
|
||||
|
||||
sort($aEntries);
|
||||
|
||||
foreach($aEntries as $sKey)
|
||||
{
|
||||
$result = apc_fetch($sKey);
|
||||
if (is_object($result))
|
||||
{
|
||||
$oSQLQuery = $result;
|
||||
if (isset($oSQLQuery->m_aContextData))
|
||||
{
|
||||
echo $oSQLQuery->m_iOriginalTableCount.";".$oSQLQuery->CountTables().';';
|
||||
foreach($oSQLQuery->m_aContextData as $oValue)
|
||||
{
|
||||
if (is_array($oValue))
|
||||
{
|
||||
$sVal = json_encode($oValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (empty($oValue))
|
||||
{
|
||||
$sVal = '';
|
||||
}
|
||||
else
|
||||
{
|
||||
$sVal = $oValue;
|
||||
}
|
||||
}
|
||||
echo $sVal.';';
|
||||
}
|
||||
echo "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
echo "</pre>";
|
||||
|
||||
354
tests/php-unit-tests/legacy-tests/replay_query_log.php
Normal file
354
tests/php-unit-tests/legacy-tests/replay_query_log.php
Normal file
@@ -0,0 +1,354 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2013-2021 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*/
|
||||
|
||||
function LogResult($sString)
|
||||
{
|
||||
file_put_contents(APPROOT.'data/queries.results.log', "\n".$sString, FILE_APPEND);
|
||||
}
|
||||
|
||||
function LogBenchmarkCSV()
|
||||
{
|
||||
$aValues = array();
|
||||
foreach (func_get_args() as $arg)
|
||||
{
|
||||
if (is_string($arg))
|
||||
{
|
||||
$aValues[] = '"'.str_replace('"', '""', $arg).'"';
|
||||
}
|
||||
else
|
||||
{
|
||||
$aValues[] = (string) $arg;
|
||||
}
|
||||
}
|
||||
$sLine = implode(';', $aValues); // the preferred for MS Excel
|
||||
file_put_contents(APPROOT.'data/queries.benchmark.csv', "\n".$sLine, FILE_APPEND);
|
||||
}
|
||||
|
||||
class QueryLogEntry
|
||||
{
|
||||
public function __construct($aLogEntryId, $aLogEntryData)
|
||||
{
|
||||
$this->aErrors = array();
|
||||
$this->sSql = '';
|
||||
$this->MakeDuration = 0;
|
||||
$this->fExecDuration = 0;
|
||||
$this->iTableCount = 0;
|
||||
$this->aRows = array();
|
||||
|
||||
$this->sLogId = $aLogEntryId;
|
||||
$this->sOql = $aLogEntryData['oql'];
|
||||
$this->sOqlHtml = htmlentities($this->sOql, ENT_QUOTES, 'UTF-8');
|
||||
|
||||
|
||||
$aQueryData = unserialize($aLogEntryData['data']);
|
||||
$this->oFilter = $aQueryData['filter'];
|
||||
$this->sClass = $this->oFilter->GetClass();
|
||||
$this->aArgs = $aQueryData['args'];
|
||||
|
||||
$iRepeat = utils::ReadParam('repeat', 3);
|
||||
|
||||
if ($aQueryData['type'] == 'select')
|
||||
{
|
||||
$this->aOrderBy = $aQueryData['order_by'];
|
||||
$this->aAttToLoad = $aQueryData['att_to_load'];
|
||||
$this->aExtendedDataSpec = $aQueryData['extended_data_spec'];
|
||||
$this->iLimitCount = $aQueryData['limit_count'];
|
||||
$this->iLimitStart = $aQueryData['limit_start'];
|
||||
$this->bGetCount = $aQueryData['is_count'];
|
||||
|
||||
if ($this->bGetCount)
|
||||
{
|
||||
$this->sQueryType = 'COUNT';
|
||||
$this->sQueryDesc = '';
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->sQueryType = 'LIST';
|
||||
$this->sQueryDesc = "limit count: $this->iLimitCount";
|
||||
$this->sQueryDesc .= "; limit start: $this->iLimitStart";
|
||||
if (count($this->aOrderBy) > 0)
|
||||
{
|
||||
$this->sQueryDesc .= "; order by: ".implode(',', array_keys($this->aOrderBy));
|
||||
}
|
||||
if (is_array($this->aAttToLoad))
|
||||
{
|
||||
$this->sQueryDesc .= "; attributes: ".implode(',', array_keys($this->aAttToLoad));
|
||||
}
|
||||
}
|
||||
|
||||
$fRefTime = MyHelpers::getmicrotime();
|
||||
try
|
||||
{
|
||||
for($i = 0 ; $i < $iRepeat ; $i++)
|
||||
{
|
||||
$this->sSql = $this->oFilter->MakeSelectQuery($this->aOrderBy, $this->aArgs, $this->aAttToLoad, $this->aExtendedDataSpec, $this->iLimitCount, $this->iLimitStart, $this->bGetCount);
|
||||
}
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
$this->aErrors[] = "Failed to create the SQL:".$e->getMessage();
|
||||
}
|
||||
$this->fMakeDuration = (MyHelpers::getmicrotime() - $fRefTime) / $iRepeat;
|
||||
}
|
||||
elseif ($aQueryData['type'] == 'group_by')
|
||||
{
|
||||
$this->aGroupByExpr = $aQueryData['group_by_expr'];
|
||||
|
||||
$this->sQueryType = 'GROUP BY';
|
||||
$aGroupedBy = array();
|
||||
foreach ($this->aGroupByExpr as $oExpr)
|
||||
{
|
||||
$aGroupedBy[] = $oExpr->Render();
|
||||
}
|
||||
$this->sQueryDesc = implode(', ', $aGroupedBy);
|
||||
|
||||
$fRefTime = MyHelpers::getmicrotime();
|
||||
try
|
||||
{
|
||||
for($i = 0 ; $i < $iRepeat ; $i++)
|
||||
{
|
||||
$this->sSql = $this->oFilter->MakeGroupByQuery($this->aArgs, $this->aGroupByExpr);
|
||||
}
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
$this->aErrors[] = "Failed to create the SQL:".$e->getMessage();
|
||||
}
|
||||
$this->fMakeDuration = (MyHelpers::getmicrotime() - $fRefTime) / $iRepeat;
|
||||
}
|
||||
else
|
||||
{
|
||||
// unsupported
|
||||
$this->sQueryType = 'ERROR';
|
||||
$this->sQueryDesc = "Unkown type of query: ".$aQueryData['type'];
|
||||
}
|
||||
}
|
||||
|
||||
public function Exec()
|
||||
{
|
||||
if ($this->sSql != '')
|
||||
{
|
||||
$iRepeat = utils::ReadParam('repeat', 3);
|
||||
try
|
||||
{
|
||||
$resQuery = null;
|
||||
$fRefTime = MyHelpers::getmicrotime();
|
||||
for($i = 0 ; $i < $iRepeat ; $i++)
|
||||
{
|
||||
$resQuery = CMDBSource::Query($this->sSql);
|
||||
}
|
||||
$this->fExecDuration = (MyHelpers::getmicrotime() - $fRefTime) / $iRepeat;
|
||||
|
||||
// This is not relevant...
|
||||
if (preg_match_all('|\s*JOIN\s*\(\s*`|', $this->sSql, $aMatches)) // JOIN (`mytable...
|
||||
{
|
||||
$this->iTableCount = 1 + count($aMatches[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->iTableCount = 1;
|
||||
}
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
$this->aErrors[] = "Failed to execute the SQL:".$e->getMessage();
|
||||
}
|
||||
if ($resQuery)
|
||||
{
|
||||
while ($aRow = CMDBSource::FetchArray($resQuery))
|
||||
{
|
||||
$this->aRows[] = $aRow;
|
||||
}
|
||||
CMDBSource::FreeResult($resQuery);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function HasErrors()
|
||||
{
|
||||
return (count($this->aErrors) > 0);
|
||||
}
|
||||
|
||||
public function Display($oP)
|
||||
{
|
||||
$oP->p($this->sOqlHtml);
|
||||
$oP->p($this->sQueryType);
|
||||
$oP->p($this->sQueryDesc);
|
||||
foreach ($this->aErrors as $sError)
|
||||
{
|
||||
$oP->p($sError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Main program
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
require_once('../../../approot.inc.php');
|
||||
require_once(APPROOT.'/application/application.inc.php');
|
||||
require_once(APPROOT.'/application/ajaxwebpage.class.inc.php');
|
||||
|
||||
require_once(APPROOT.'/application/startup.inc.php');
|
||||
$operation = utils::ReadParam('operation', '');
|
||||
|
||||
require_once(APPROOT.'/application/loginwebpage.class.inc.php');
|
||||
LoginWebPage::DoLogin(); // Check user rights and prompt if needed
|
||||
|
||||
$oP = new WebPage('Replay queries.log');
|
||||
|
||||
|
||||
ini_set('memory_limit', '512M');
|
||||
|
||||
require_once(APPROOT.'/data/queries.log');
|
||||
$iCount = count($aQueriesLog);
|
||||
$oP->p("Nombre de requêtes: ".$iCount);
|
||||
|
||||
$sOperation = utils::ReadParam('operation', '');
|
||||
|
||||
switch ($sOperation)
|
||||
{
|
||||
case '':
|
||||
default:
|
||||
$oP->add("<ol>\n");
|
||||
foreach ($aQueriesLog as $sQueryId => $aOqlData)
|
||||
{
|
||||
$sOql = $aOqlData['oql'];
|
||||
$sOqlHtml = htmlentities($sOql, ENT_QUOTES, 'UTF-8');
|
||||
$oP->add("<li>$sOqlHtml <a href=\"?operation=zoom&query=$sQueryId\">zoom</a></li>\n");
|
||||
}
|
||||
$oP->add("</ol>\n");
|
||||
|
||||
$oP->add("<form action=\"?operation=benchmark&repeat=3\" method=\"post\">\n");
|
||||
$oP->add("<input type=\"submit\" value=\"Benchmark (3 repeats)!\">\n");
|
||||
$oP->add("</form>\n");
|
||||
|
||||
$oP->add("<form action=\"?operation=check\" method=\"post\">\n");
|
||||
$oP->add("<input type=\"submit\" value=\"Check!\">\n");
|
||||
$oP->add("</form>\n");
|
||||
break;
|
||||
|
||||
case 'zoom':
|
||||
$sQueryId = utils::ReadParam('query', '', false, 'raw_data');
|
||||
$oP->add("<h2>Zoom on query</h2>\n");
|
||||
$oQuery = new QueryLogEntry($sQueryId, $aQueriesLog[$sQueryId]);
|
||||
$oQuery->Exec();
|
||||
$oQuery->Display($oP);
|
||||
|
||||
$oP->add("<pre>$oQuery->sSql</pre>\n");
|
||||
$oP->p("Tables: $oQuery->iTableCount");
|
||||
|
||||
if (strlen($oQuery->sSql) > 0)
|
||||
{
|
||||
$aExplain = CMDBSource::ExplainQuery($oQuery->sSql);
|
||||
$oP->add("<h4>Explain</h4>\n");
|
||||
$oP->add("<table style=\"border=1px;\">\n");
|
||||
foreach ($aExplain as $aRow)
|
||||
{
|
||||
$oP->add(" <tr>\n");
|
||||
$oP->add(" <td>".implode('</td><td>', $aRow)."</td>\n");
|
||||
$oP->add(" </tr>\n");
|
||||
}
|
||||
$oP->add("</table>\n");
|
||||
}
|
||||
|
||||
if (count($oQuery->aRows))
|
||||
{
|
||||
$oP->add("<h4>Values</h4>\n");
|
||||
$oP->add("<table style=\"border=1px;\">\n");
|
||||
foreach ($oQuery->aRows as $iRow => $aRow)
|
||||
{
|
||||
$oP->add(" <tr>\n");
|
||||
$oP->add(" <td>".implode('</td><td>', $aRow)."</td>\n");
|
||||
$oP->add(" </tr>\n");
|
||||
}
|
||||
$oP->add("</table>\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
$oP->p("No data");
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case 'check':
|
||||
$oP->add("<h2>List queries in error</h2>\n");
|
||||
foreach ($aQueriesLog as $sQueryId => $aOqlData)
|
||||
{
|
||||
$oQuery = new QueryLogEntry($sQueryId, $aOqlData);
|
||||
$oQuery->Exec();
|
||||
|
||||
if ($oQuery->HasErrors())
|
||||
{
|
||||
$oQuery->Display($oP);
|
||||
$oP->p("<a href=\"?operation=zoom&query=$sQueryId\">zoom</a>");
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case 'benchmark':
|
||||
$oP->add("<h2>Create data/queries.xxx reports</h2>\n");
|
||||
// Reset the log contents
|
||||
file_put_contents(APPROOT.'data/queries.results.log', date('Y-m-d H:i:s')."\n");
|
||||
file_put_contents(APPROOT.'data/queries.benchmark.csv', '');
|
||||
LogBenchmarkCSV('type', 'properties', 'make duration', 'class', 'tables', 'query length', 'exec duration', 'rows', 'oql');
|
||||
|
||||
$iErrors = 0;
|
||||
|
||||
foreach ($aQueriesLog as $sQueryId => $aOqlData)
|
||||
{
|
||||
$oQuery = new QueryLogEntry($sQueryId, $aOqlData);
|
||||
$oQuery->Exec();
|
||||
|
||||
LogResult('-----------------------------------------------------------');
|
||||
LogResult($oQuery->sOql);
|
||||
LogResult($oQuery->sQueryType);
|
||||
if (strlen($oQuery->sQueryDesc) > 0)
|
||||
{
|
||||
LogResult($oQuery->sQueryDesc);
|
||||
}
|
||||
|
||||
if ($oQuery->HasErrors())
|
||||
{
|
||||
foreach($oQuery->aErrors as $sError)
|
||||
{
|
||||
LogResult($sError);
|
||||
$iErrors++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogResult("row count = ".count($oQuery->aRows));
|
||||
foreach($oQuery->aRows as $iRow => $aRow)
|
||||
{
|
||||
LogResult("row: ".serialize($aRow));
|
||||
if ($iRow > 100) break;
|
||||
}
|
||||
|
||||
LogBenchmarkCSV($oQuery->sQueryType, $oQuery->sQueryDesc, sprintf('%1.3f', round($oQuery->fMakeDuration, 3)), $oQuery->sClass, $oQuery->iTableCount, strlen($oQuery->sSql), sprintf('%1.4f', round($oQuery->fExecDuration, 4)), count($oQuery->aRows), $oQuery->sOql);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$oP->output();
|
||||
?>
|
||||
551
tests/php-unit-tests/legacy-tests/test.class.inc.php
Normal file
551
tests/php-unit-tests/legacy-tests/test.class.inc.php
Normal file
@@ -0,0 +1,551 @@
|
||||
<?php
|
||||
// Copyright (C) 2010-2021 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// iTop is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
/**
|
||||
* Core automated tests - basics
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
|
||||
require_once(APPROOT.'/core/attributedef.class.inc.php');
|
||||
require_once(APPROOT.'/core/filterdef.class.inc.php');
|
||||
require_once(APPROOT.'/core/stimulus.class.inc.php');
|
||||
require_once(APPROOT.'/core/MyHelpers.class.inc.php');
|
||||
|
||||
require_once(APPROOT.'/core/oql/expression.class.inc.php');
|
||||
require_once(APPROOT.'/core/cmdbsource.class.inc.php');
|
||||
require_once(APPROOT.'/core/sqlquery.class.inc.php');
|
||||
require_once(APPROOT.'/core/sqlobjectquery.class.inc.php');
|
||||
require_once(APPROOT.'/core/sqlunionquery.class.inc.php');
|
||||
|
||||
require_once(APPROOT.'/core/log.class.inc.php');
|
||||
require_once(APPROOT.'/core/kpi.class.inc.php');
|
||||
|
||||
require_once(APPROOT.'/core/dbobject.class.php');
|
||||
require_once(APPROOT.'/core/dbsearch.class.php');
|
||||
require_once(APPROOT.'/core/dbobjectset.class.php');
|
||||
|
||||
require_once(APPROOT.'/application/cmdbabstract.class.inc.php');
|
||||
|
||||
require_once(APPROOT.'/core/userrights.class.inc.php');
|
||||
|
||||
require_once(APPROOT.'/webservices/webservices.class.inc.php');
|
||||
|
||||
|
||||
// Just to differentiate programmatically triggered exceptions and other kind of errors (usefull?)
|
||||
class UnitTestException extends Exception
|
||||
{}
|
||||
|
||||
|
||||
/**
|
||||
* Improved display of the backtrace
|
||||
*
|
||||
* @package iTopORM
|
||||
*/
|
||||
class ExceptionFromError extends Exception
|
||||
{
|
||||
public function getTraceAsHtml()
|
||||
{
|
||||
$aBackTrace = $this->getTrace();
|
||||
return MyHelpers::get_callstack_html(0, $this->getTrace());
|
||||
// return "<pre>\n".$this->getTraceAsString()."</pre>\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test handler API and basic helpers
|
||||
*
|
||||
* @package iTopORM
|
||||
*/
|
||||
abstract class TestHandler
|
||||
{
|
||||
protected $m_aSuccesses;
|
||||
protected $m_aWarnings;
|
||||
protected $m_aErrors;
|
||||
protected $m_sOutput;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->m_aSuccesses = array();
|
||||
$this->m_aWarnings = array();
|
||||
$this->m_aErrors = array();
|
||||
}
|
||||
|
||||
static public function GetName() {return "fooname";}
|
||||
static public function GetDescription(){return "foodesc";}
|
||||
|
||||
protected function DoPrepare() {return true;}
|
||||
abstract protected function DoExecute();
|
||||
protected function DoCleanup() {return true;}
|
||||
|
||||
protected static function DumpVariable($var)
|
||||
{
|
||||
echo "<pre class=\"vardump\">\n";
|
||||
print_r($var);
|
||||
echo "</pre>\n";
|
||||
}
|
||||
|
||||
protected function ReportSuccess($sMessage, $sSubtestId = '')
|
||||
{
|
||||
$this->m_aSuccesses[] = $sMessage;
|
||||
}
|
||||
|
||||
protected function ReportWarning($sMessage, $sSubtestId = '')
|
||||
{
|
||||
$this->m_aWarnings[] = $sMessage;
|
||||
}
|
||||
|
||||
protected function ReportError($sMessage, $sSubtestId = '')
|
||||
{
|
||||
$this->m_aErrors[] = $sMessage;
|
||||
}
|
||||
|
||||
public function GetResults()
|
||||
{
|
||||
return $this->m_aSuccesses;
|
||||
}
|
||||
|
||||
public function GetWarnings()
|
||||
{
|
||||
return $this->m_aWarnings;
|
||||
}
|
||||
|
||||
public function GetErrors()
|
||||
{
|
||||
return $this->m_aErrors;
|
||||
}
|
||||
|
||||
public function GetOutput()
|
||||
{
|
||||
return $this->m_sOutput;
|
||||
}
|
||||
|
||||
public function error_handler($errno, $errstr, $errfile, $errline)
|
||||
{
|
||||
// Note: return false to call the default handler (stop the program if an error)
|
||||
|
||||
if ($errstr == 'assert()') $errno = E_USER_ERROR;
|
||||
|
||||
switch ($errno)
|
||||
{
|
||||
case E_USER_ERROR:
|
||||
case E_WARNING: //(assertion failed)
|
||||
$this->ReportError("$errfile@$errline - $errstr");
|
||||
break;
|
||||
case E_USER_WARNING:
|
||||
$this->ReportWarning("$errfile@$errline - $errstr");
|
||||
break;
|
||||
case E_USER_NOTICE:
|
||||
$this->ReportWarning("$errfile@$errline - $errstr");
|
||||
break;
|
||||
default:
|
||||
$this->ReportWarning("$errfile@$errline - Unknown error type: [$errno] $errstr");
|
||||
echo "Unknown error type: [$errno] $errstr in $errfile at $errline<br />\n";
|
||||
break;
|
||||
}
|
||||
return true; // do not call the default handler
|
||||
}
|
||||
|
||||
public function Execute()
|
||||
{
|
||||
ob_start();
|
||||
set_error_handler(array($this, 'error_handler'));
|
||||
try
|
||||
{
|
||||
$this->DoPrepare();
|
||||
$this->DoExecute();
|
||||
}
|
||||
catch (ExceptionFromError $e)
|
||||
{
|
||||
$this->ReportError($e->getMessage().' - '.$e->getTraceAsHtml());
|
||||
}
|
||||
catch (CoreException $e)
|
||||
{
|
||||
//$this->ReportError($e->getMessage());
|
||||
//$this->ReportError($e->__tostring());
|
||||
$this->ReportError($e->getMessage().' - '.$e->getTraceAsHtml());
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
//$this->ReportError($e->getMessage());
|
||||
//$this->ReportError($e->__tostring());
|
||||
$this->ReportError('class '.get_class($e).' --- '.$e->getMessage().' - '.$e->getTraceAsString());
|
||||
}
|
||||
restore_error_handler();
|
||||
$this->m_sOutput = ob_get_clean();
|
||||
return (count($this->GetErrors()) == 0);
|
||||
}
|
||||
|
||||
static protected function DoPostRequestAuth($sRelativeUrl, $aData, $sLogin = 'admin', $sPassword = 'admin', $sOptionnalHeaders = null)
|
||||
{
|
||||
$aDataAndAuth = $aData;
|
||||
// To be changed to use basic authentication
|
||||
$aDataAndAuth['operation'] = 'login';
|
||||
$aDataAndAuth['auth_user'] = $sLogin;
|
||||
$aDataAndAuth['auth_pwd'] = $sPassword;
|
||||
$sHost = $_SERVER['HTTP_HOST'];
|
||||
$sRawPath = $_SERVER['SCRIPT_NAME'];
|
||||
$sPath = dirname($sRawPath);
|
||||
$sUrl = "http://$sHost/$sPath/$sRelativeUrl";
|
||||
|
||||
return self::DoPostRequest($sUrl, $aDataAndAuth, $sOptionnalHeaders);
|
||||
}
|
||||
|
||||
// Source: http://netevil.org/blog/2006/nov/http-post-from-php-without-curl
|
||||
// originaly named after do_post_request
|
||||
// Partially adapted to our coding conventions
|
||||
static protected function DoPostRequest($sUrl, $aData, $sOptionnalHeaders = null)
|
||||
{
|
||||
// $sOptionnalHeaders is a string containing additional HTTP headers that you would like to send in your request.
|
||||
|
||||
$sData = http_build_query($aData);
|
||||
|
||||
$aParams = array('http' => array(
|
||||
'method' => 'POST',
|
||||
'content' => $sData,
|
||||
'header'=> "Content-type: application/x-www-form-urlencoded\r\nContent-Length: ".strlen($sData)."\r\n",
|
||||
));
|
||||
if ($sOptionnalHeaders !== null)
|
||||
{
|
||||
$aParams['http']['header'] .= $sOptionnalHeaders;
|
||||
}
|
||||
$ctx = stream_context_create($aParams);
|
||||
|
||||
$fp = @fopen($sUrl, 'rb', false, $ctx);
|
||||
if (!$fp)
|
||||
{
|
||||
global $php_errormsg;
|
||||
if (isset($php_errormsg))
|
||||
{
|
||||
throw new Exception("Problem with $sUrl, $php_errormsg");
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Problem with $sUrl");
|
||||
}
|
||||
}
|
||||
$response = @stream_get_contents($fp);
|
||||
if ($response === false)
|
||||
{
|
||||
throw new Exception("Problem reading data from $sUrl, $php_errormsg");
|
||||
}
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Test to execute a piece of code (checks if an error occurs)
|
||||
*
|
||||
* @package iTopORM
|
||||
*/
|
||||
abstract class TestFunction extends TestHandler
|
||||
{
|
||||
// simply overload DoExecute (temporary)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test to execute a piece of code (checks if an error occurs)
|
||||
*
|
||||
* @package iTopORM
|
||||
*/
|
||||
abstract class TestWebServices extends TestHandler
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to execute a piece of code (checks if an error occurs)
|
||||
*
|
||||
* @package iTopORM
|
||||
*/
|
||||
abstract class TestSoapWebService extends TestHandler
|
||||
{
|
||||
// simply overload DoExecute (temporary)
|
||||
|
||||
function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to check that a function outputs some values depending on its input
|
||||
*
|
||||
* @package iTopORM
|
||||
*/
|
||||
abstract class TestFunctionInOut extends TestFunction
|
||||
{
|
||||
// abstract static public function GetCallSpec(); // parameters to call_user_func
|
||||
// abstract static public function GetInOut(); // array of input => output
|
||||
|
||||
protected function DoExecute()
|
||||
{
|
||||
$aTests = $this->GetInOut();
|
||||
if (is_array($aTests))
|
||||
{
|
||||
foreach ($aTests as $iTestId => $aTest)
|
||||
{
|
||||
$ret = call_user_func_array($this->GetCallSpec(), $aTest['args']);
|
||||
if ($ret != $aTest['output'])
|
||||
{
|
||||
// Note: to be improved to cope with non string parameters
|
||||
$this->ReportError("Found '$ret' while expecting '".$aTest['output']."'", $iTestId);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->ReportSuccess("Found the expected output '$ret'", $iTestId);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$ret = call_user_func($this->GetCallSpec());
|
||||
$this->ReportSuccess('Finished successfully');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test to check an URL (Searches for Error/Warning/Etc keywords)
|
||||
*
|
||||
* @package iTopORM
|
||||
*/
|
||||
abstract class TestUrl extends TestHandler
|
||||
{
|
||||
// abstract static public function GetUrl();
|
||||
// abstract static public function GetErrorKeywords();
|
||||
// abstract static public function GetWarningKeywords();
|
||||
|
||||
protected function DoExecute()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test to check a user management module
|
||||
*
|
||||
* @package iTopORM
|
||||
*/
|
||||
abstract class TestUserRights extends TestHandler
|
||||
{
|
||||
protected function DoExecute()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test to execute a scenario on a given DB
|
||||
*
|
||||
* @package iTopORM
|
||||
*/
|
||||
abstract class TestScenarioOnDB extends TestHandler
|
||||
{
|
||||
// abstract static public function GetDBHost();
|
||||
// abstract static public function GetDBUser();
|
||||
// abstract static public function GetDBPwd();
|
||||
// abstract static public function GetDBName();
|
||||
|
||||
protected function DoPrepare()
|
||||
{
|
||||
$sDBHost = $this->GetDBHost();
|
||||
$sDBUser = $this->GetDBUser();
|
||||
$sDBPwd = $this->GetDBPwd();
|
||||
$sDBName = $this->GetDBName();
|
||||
|
||||
CMDBSource::Init($sDBHost, $sDBUser, $sDBPwd);
|
||||
CMDBSource::SetCharacterSet();
|
||||
if (CMDBSource::IsDB($sDBName))
|
||||
{
|
||||
CMDBSource::DropDB($sDBName);
|
||||
}
|
||||
CMDBSource::CreateDB($sDBName);
|
||||
}
|
||||
|
||||
protected function DoCleanup()
|
||||
{
|
||||
// CMDBSource::DropDB($this->GetDBName());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test to use a business model on a given DB
|
||||
*
|
||||
* @package iTopORM
|
||||
*/
|
||||
abstract class TestBizModel extends TestHandler
|
||||
{
|
||||
// abstract static public function GetDBSubName();
|
||||
// abstract static public function GetBusinessModelFile();
|
||||
// abstract static public function GetConfigFile();
|
||||
|
||||
static public function GetConfigFile() {return 'conf/production/config-itop.php';}
|
||||
|
||||
protected function DoPrepare()
|
||||
{
|
||||
$sConfigFile = APPROOT.$this->GetConfigFile();
|
||||
MetaModel::Startup($sConfigFile);
|
||||
// #@# Temporary disabled by Romain
|
||||
// MetaModel::CheckDefinitions();
|
||||
|
||||
// something here to create records... but that's another story
|
||||
}
|
||||
|
||||
protected $m_oChange;
|
||||
protected function GetCurrentChange()
|
||||
{
|
||||
if (!isset($this->m_oChange))
|
||||
{
|
||||
new CMDBChange();
|
||||
$oMyChange = MetaModel::NewObject("CMDBChange");
|
||||
$oMyChange->Set("date", time());
|
||||
$oMyChange->Set("userinfo", "Someone doing some tests");
|
||||
$iChangeId = $oMyChange->DBInsertNoReload();
|
||||
$this->m_oChange = $oMyChange;
|
||||
}
|
||||
return $this->m_oChange;
|
||||
}
|
||||
protected function ObjectToDB($oNew, $bReload = false)
|
||||
{
|
||||
if ($bReload)
|
||||
{
|
||||
$iId = $oNew->DBInsert();
|
||||
}
|
||||
else
|
||||
{
|
||||
$iId = $oNew->DBInsertNoReload();
|
||||
}
|
||||
return $iId;
|
||||
}
|
||||
|
||||
protected function UpdateObjectInDB($oObject)
|
||||
{
|
||||
$oObject->DBUpdate();
|
||||
}
|
||||
protected function ResetDB()
|
||||
{
|
||||
if (MetaModel::DBExists(false))
|
||||
{
|
||||
MetaModel::DBDrop();
|
||||
}
|
||||
MetaModel::DBCreate();
|
||||
}
|
||||
|
||||
static protected function show_list($oObjectSet)
|
||||
{
|
||||
$oObjectSet->Rewind();
|
||||
$aData = array();
|
||||
while ($oItem = $oObjectSet->Fetch())
|
||||
{
|
||||
$aValues = array();
|
||||
foreach(MetaModel::GetAttributesList(get_class($oItem)) as $sAttCode)
|
||||
{
|
||||
$aValues[$sAttCode] = $oItem->GetAsHTML($sAttCode);
|
||||
}
|
||||
//echo $oItem->GetKey()." => ".implode(", ", $aValues)."</br>\n";
|
||||
$aData[] = $aValues;
|
||||
}
|
||||
echo MyHelpers::make_table_from_assoc_array($aData);
|
||||
}
|
||||
|
||||
static protected function search_and_show_list(DBSearch $oMyFilter)
|
||||
{
|
||||
$oObjSet = new CMDBObjectSet($oMyFilter);
|
||||
echo $oMyFilter->ToOQL()."' - Found ".$oObjSet->Count()." items.</br>\n";
|
||||
self::show_list($oObjSet);
|
||||
}
|
||||
|
||||
static protected function search_and_show_list_from_oql($sOQL)
|
||||
{
|
||||
echo $sOQL."...<br/>\n";
|
||||
$oNewFilter = DBObjectSearch::FromOQL($sOQL);
|
||||
self::search_and_show_list($oNewFilter);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test to execute a scenario common to any business model (tries to build all the possible queries, etc.)
|
||||
*
|
||||
* @package iTopORM
|
||||
*/
|
||||
abstract class TestBizModelGeneric extends TestBizModel
|
||||
{
|
||||
static public function GetName()
|
||||
{
|
||||
return 'Full test on a given business model';
|
||||
}
|
||||
|
||||
static public function GetDescription()
|
||||
{
|
||||
return 'Systematic tests: gets each and every existing class and tries every attribute, search filters, etc.';
|
||||
}
|
||||
|
||||
protected function DoPrepare()
|
||||
{
|
||||
parent::DoPrepare();
|
||||
|
||||
if (!MetaModel::DBExists(false))
|
||||
{
|
||||
MetaModel::DBCreate();
|
||||
}
|
||||
// something here to create records... but that's another story
|
||||
}
|
||||
|
||||
protected function DoExecute()
|
||||
{
|
||||
foreach(MetaModel::GetClasses() as $sClassName)
|
||||
{
|
||||
if (MetaModel::HasTable($sClassName)) continue;
|
||||
|
||||
$oNobody = MetaModel::GetObject($sClassName, 123);
|
||||
$oBaby = new $sClassName;
|
||||
$oFilter = new DBObjectSearch($sClassName);
|
||||
|
||||
// Challenge reversibility of OQL / filter object
|
||||
//
|
||||
$sExpr1 = $oFilter->ToOQL();
|
||||
$oNewFilter = DBObjectSearch::FromOQL($sExpr1);
|
||||
$sExpr2 = $oNewFilter->ToOQL();
|
||||
if ($sExpr1 != $sExpr2)
|
||||
{
|
||||
$this->ReportError("Found two different OQL expression out of the (same?) filter: <em>$sExpr1</em> != <em>$sExpr2</em>");
|
||||
}
|
||||
|
||||
// Use the filter (perform the query)
|
||||
//
|
||||
$oSet = new CMDBObjectSet($oFilter);
|
||||
$this->ReportSuccess('Found '.$oSet->Count()." objects of class $sClassName");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
?>
|
||||
162
tests/php-unit-tests/legacy-tests/test.php
Normal file
162
tests/php-unit-tests/legacy-tests/test.php
Normal file
@@ -0,0 +1,162 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2013-2021 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*/
|
||||
|
||||
?>
|
||||
<style>
|
||||
.vardump {
|
||||
font-size:8pt;
|
||||
line-height:100%;
|
||||
}
|
||||
</style>
|
||||
<?php
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Helpers
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function ReadMandatoryParam($sName)
|
||||
{
|
||||
$value = utils::ReadParam($sName, null);
|
||||
if (is_null($value))
|
||||
{
|
||||
echo "<p>Missing mandatory argument <b>$sName</b></p>";
|
||||
exit;
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
function IsAValidTestClass($sClassName)
|
||||
{
|
||||
// Must be a child of TestHandler
|
||||
//
|
||||
if (!is_subclass_of($sClassName, 'TestHandler')) return false;
|
||||
|
||||
// Must not be abstract
|
||||
//
|
||||
$oReflectionClass = new ReflectionClass($sClassName);
|
||||
if (!$oReflectionClass->isInstantiable()) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function GetTestClassLine($sClassName)
|
||||
{
|
||||
$oReflectionClass = new ReflectionClass($sClassName);
|
||||
return $oReflectionClass->getStartLine();
|
||||
}
|
||||
|
||||
function DisplayEvents($aEvents, $sTitle)
|
||||
{
|
||||
echo "<h4>$sTitle</h4>\n";
|
||||
if (count($aEvents) > 0)
|
||||
{
|
||||
echo "<ul>\n";
|
||||
foreach ($aEvents as $sEvent)
|
||||
{
|
||||
echo "<li>$sEvent</li>\n";
|
||||
}
|
||||
echo "</ul>\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
echo "<p>none</p>\n";
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Main
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
date_default_timezone_set('Europe/Paris');
|
||||
|
||||
require_once('../../../approot.inc.php');
|
||||
require_once(APPROOT.'/application/utils.inc.php');
|
||||
require_once('./test.class.inc.php');
|
||||
require_once('./testlist.inc.php');
|
||||
|
||||
require_once(APPROOT.'/core/cmdbobject.class.inc.php');
|
||||
|
||||
|
||||
$sTodo = utils::ReadParam("todo", "");
|
||||
if ($sTodo == '')
|
||||
{
|
||||
// Show the list of tests
|
||||
//
|
||||
echo "<h3>Existing tests</h3>\n";
|
||||
echo "<ul>\n";
|
||||
foreach (get_declared_classes() as $sClassName)
|
||||
{
|
||||
if (!IsAValidTestClass($sClassName)) continue;
|
||||
|
||||
$sName = call_user_func(array($sClassName, 'GetName'));
|
||||
$sDescription = call_user_func(array($sClassName, 'GetDescription'));
|
||||
echo "<li><a href=\"?todo=exec&testid=$sClassName\">$sName</a> ($sDescription)</li>\n";
|
||||
}
|
||||
echo "</ul>\n";
|
||||
}
|
||||
else if ($sTodo == 'exec')
|
||||
{
|
||||
// Execute a test
|
||||
//
|
||||
$sTestClass = ReadMandatoryParam("testid");
|
||||
|
||||
if (!IsAValidTestClass($sTestClass))
|
||||
{
|
||||
echo "<p>Wrong value for testid, expecting a valid class name</p>\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
$oTest = new $sTestClass();
|
||||
$iStartLine = GetTestClassLine($sTestClass);
|
||||
echo "<h3>Testing: ".$oTest->GetName()."</h3>\n";
|
||||
echo "<h6>testlist.inc.php: $iStartLine</h6>\n";
|
||||
$bRes = $oTest->Execute();
|
||||
}
|
||||
|
||||
/*
|
||||
MyHelpers::var_dump_html($oTest->GetResults());
|
||||
MyHelpers::var_dump_html($oTest->GetWarnings());
|
||||
MyHelpers::var_dump_html($oTest->GetErrors());
|
||||
*/
|
||||
|
||||
if ($bRes)
|
||||
{
|
||||
echo "<p>Success :-)</p>\n";
|
||||
DisplayEvents($oTest->GetResults(), 'Results');
|
||||
}
|
||||
else
|
||||
{
|
||||
echo "<p>Failure :-(</p>\n";
|
||||
}
|
||||
DisplayEvents($oTest->GetErrors(), 'Errors');
|
||||
DisplayEvents($oTest->GetWarnings(), 'Warnings');
|
||||
|
||||
// Render the output
|
||||
//
|
||||
echo "<h4>Actual output</h4>\n";
|
||||
echo "<div style=\"border: dashed; background-color:light-grey;\">\n";
|
||||
echo $oTest->GetOutput();
|
||||
echo "</div>\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
?>
|
||||
4114
tests/php-unit-tests/legacy-tests/testlist.inc.php
Normal file
4114
tests/php-unit-tests/legacy-tests/testlist.inc.php
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user