소스 검색

#154 Application too slow - no need to check the DB format anytime!

git-svn-id: http://svn.code.sf.net/p/itop/code/trunk@594 a333f486-631f-4898-b8df-5754b55c2be0
romainq 15 년 전
부모
커밋
220c6297b3
6개의 변경된 파일565개의 추가작업 그리고 569개의 파일을 삭제
  1. 6 16
      core/metamodel.class.php
  2. 12 8
      core/sqlquery.class.inc.php
  3. 537 536
      core/test.class.inc.php
  4. 1 1
      pages/ITopConsultant.php
  5. 7 6
      setup/index.php
  6. 2 2
      setup/xmldataloader.class.inc.php

+ 6 - 16
core/metamodel.class.php

@@ -3089,25 +3089,15 @@ abstract class MetaModel
 		}
 	}
 
-	public static function Startup($sConfigFile, $bAllowMissingDB = false)
+	public static function Startup($sConfigFile, $bModelOnly = false)
 	{
 		self::LoadConfig($sConfigFile);
-		if (self::DBExists())
-// !!!! #@# 
-		//if (true)
-		{
-			CMDBSource::SelectDB(self::$m_sDBName);
+		if ($bModelOnly) return;
 
-			// Some of the init could not be done earlier (requiring classes to be declared and DB to be accessible)
-			self::InitPlugins();
-		}
-		else
-		{
-			if (!$bAllowMissingDB)
-			{
-				throw new CoreException('Database not found, check your configuration file', array('config_file'=>$sConfigFile, 'db_name'=>self::$m_sDBName));
-			}
-		}
+		CMDBSource::SelectDB(self::$m_sDBName);
+
+		// Some of the init could not be done earlier (requiring classes to be declared and DB to be accessible)
+		self::InitPlugins();
 	}
 
 	public static function LoadConfig($sConfigFile)

+ 12 - 8
core/sqlquery.class.inc.php

@@ -66,10 +66,12 @@ class SQLQuery
 
 	public function __construct($sTable, $sTableAlias, $aFields, $oConditionExpr, $aFullTextNeedles, $bToDelete = true, $aValues = array())
 	{
-		if (!CMDBSource::IsTable($sTable))
-		{
-			throw new CoreException("Unknown table '$sTable'");
-		}
+		// This check is not needed but for developping purposes
+		//if (!CMDBSource::IsTable($sTable))
+		//{
+		//	throw new CoreException("Unknown table '$sTable'");
+		//}
+
 		// $aFields must be an array of "alias"=>"expr"
 		// $oConditionExpr must be a condition tree
 		// $aValues is an array of "alias"=>value
@@ -157,10 +159,12 @@ class SQLQuery
 	private function AddJoin($sJoinType, $oSQLQuery, $sLeftField, $sRightField, $sRightTableAlias = '')
 	{
 		assert((get_class($oSQLQuery) == __CLASS__) || is_subclass_of($oSQLQuery, __CLASS__));
-		if (!CMDBSource::IsField($this->m_sTable, $sLeftField))
-		{
-			throw new CoreException("Unknown field '$sLeftField' in table '".$this->m_sTable);
-		}
+		// No need to check this here but for development purposes
+		//if (!CMDBSource::IsField($this->m_sTable, $sLeftField))
+		//{
+		//	throw new CoreException("Unknown field '$sLeftField' in table '".$this->m_sTable);
+		//}
+
 		if (empty($sRightTableAlias))
 		{
 			$sRightTableAlias = $oSQLQuery->m_sTableAlias;

+ 537 - 536
core/test.class.inc.php

@@ -1,536 +1,537 @@
-<?php
-// Copyright (C) 2010 Combodo SARL
-//
-//   This program is free software; you can redistribute it and/or modify
-//   it under the terms of the GNU General Public License as published by
-//   the Free Software Foundation; version 3 of the License.
-//
-//   This program 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 General Public License for more details.
-//
-//   You should have received a copy of the GNU General Public License
-//   along with this program; if not, write to the Free Software
-//   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-
-/**
- * Core automated tests - basics
- *
- * @author      Erwan Taloc <erwan.taloc@combodo.com>
- * @author      Romain Quetiez <romain.quetiez@combodo.com>
- * @author      Denis Flaven <denis.flaven@combodo.com>
- * @license     http://www.opensource.org/licenses/gpl-3.0.html LGPL
- */
-
-
-require_once('coreexception.class.inc.php');
-require_once('attributedef.class.inc.php');
-require_once('filterdef.class.inc.php');
-require_once('stimulus.class.inc.php');
-require_once('MyHelpers.class.inc.php');
-
-require_once('expression.class.inc.php');
-require_once('cmdbsource.class.inc.php');
-require_once('sqlquery.class.inc.php');
-
-require_once('log.class.inc.php');
-
-require_once('dbobject.class.php');
-require_once('dbobjectsearch.class.php');
-require_once('dbobjectset.class.php');
-
-require_once('userrights.class.inc.php');
-
-require_once('../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();
-	}
-
-	abstract static public function GetName();
-	abstract static public function GetDescription();
-
-	protected function DoPrepare() {return true;}
-	abstract protected function DoExecute();
-	protected function DoCleanup() {return true;}
-
-	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)
-
-		switch ($errno)
-		{
-		case E_USER_ERROR:
-			$this->ReportError($errstr);
-			//throw new ExceptionFromError("Fatal error in line $errline of file $errfile: $errstr");
-			break;
-		case E_USER_WARNING:
-			$this->ReportWarning($errstr);
-			break;
-		case E_USER_NOTICE:
-			$this->ReportWarning($errstr);
-			break;
-		default:
-			$this->ReportWarning("Unknown error type: [$errno] $errstr in $errfile at $errline");
-			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);
-	}
-}
-
-
-
-
-/**
- * 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
-{
-	// simply overload DoExecute (temporary)
-
-	static protected function DoPostRequestAuth($sRelativeUrl, $aData, $sLogin = 'admin', $sPassword = 'admin', $sOptionnalHeaders = null)
-	{
-		$aDataAndAuth = $aData;
-		$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)
-		{
-			throw new Exception("Problem with $sUrl, $php_errormsg");
-		}
-		$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 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);
-		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();
-
-	protected function DoPrepare()
-	{
-		MetaModel::Startup($this->GetConfigFile(), true); // allow missing DB
-		MetaModel::CheckDefinitions();
-
-		// something here to create records... but that's another story
-	}
-
-	protected $m_oChange;
-	protected function ObjectToDB($oNew, $bReload = false)
-	{
-		list($bRes, $aIssues) = $oNew->CheckToInsert();
-		if (!$bRes)
-		{
-			throw new CoreException('Could not create object, unexpected values', array('attributes' => $aIssues));
-		}
-		if ($oNew instanceof CMDBObject)
-		{
-			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; 
-			}
-			if ($bReload)
-			{
-				$iId = $oNew->DBInsertTracked($this->m_oChange);
-			}
-			else
-			{
-				$iId = $oNew->DBInsertTrackedNoReload($this->m_oChange);
-			}
-		}
-		else
-		{
-			if ($bReload)
-			{
-				$iId = $oNew->DBInsert();
-			}
-			else
-			{
-				$iId = $oNew->DBInsertNoReload();
-			}
-		}
-		return $iId;
-	}
-
-	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(DBObjectSearch $oMyFilter)
-	{
-		$oObjSet = new CMDBObjectSet($oMyFilter);
-		echo $oMyFilter->__DescribeHTML()."' - 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;
-	}
-}
-
-
-?>
+<?php
+// Copyright (C) 2010 Combodo SARL
+//
+//   This program is free software; you can redistribute it and/or modify
+//   it under the terms of the GNU General Public License as published by
+//   the Free Software Foundation; version 3 of the License.
+//
+//   This program 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 General Public License for more details.
+//
+//   You should have received a copy of the GNU General Public License
+//   along with this program; if not, write to the Free Software
+//   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+/**
+ * Core automated tests - basics
+ *
+ * @author      Erwan Taloc <erwan.taloc@combodo.com>
+ * @author      Romain Quetiez <romain.quetiez@combodo.com>
+ * @author      Denis Flaven <denis.flaven@combodo.com>
+ * @license     http://www.opensource.org/licenses/gpl-3.0.html LGPL
+ */
+
+
+require_once('coreexception.class.inc.php');
+require_once('attributedef.class.inc.php');
+require_once('filterdef.class.inc.php');
+require_once('stimulus.class.inc.php');
+require_once('MyHelpers.class.inc.php');
+
+require_once('expression.class.inc.php');
+require_once('cmdbsource.class.inc.php');
+require_once('sqlquery.class.inc.php');
+
+require_once('log.class.inc.php');
+
+require_once('dbobject.class.php');
+require_once('dbobjectsearch.class.php');
+require_once('dbobjectset.class.php');
+
+require_once('userrights.class.inc.php');
+
+require_once('../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();
+	}
+
+	abstract static public function GetName();
+	abstract static public function GetDescription();
+
+	protected function DoPrepare() {return true;}
+	abstract protected function DoExecute();
+	protected function DoCleanup() {return true;}
+
+	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)
+
+		switch ($errno)
+		{
+		case E_USER_ERROR:
+			$this->ReportError($errstr);
+			//throw new ExceptionFromError("Fatal error in line $errline of file $errfile: $errstr");
+			break;
+		case E_USER_WARNING:
+			$this->ReportWarning($errstr);
+			break;
+		case E_USER_NOTICE:
+			$this->ReportWarning($errstr);
+			break;
+		default:
+			$this->ReportWarning("Unknown error type: [$errno] $errstr in $errfile at $errline");
+			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);
+	}
+}
+
+
+
+
+/**
+ * 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
+{
+	// simply overload DoExecute (temporary)
+
+	static protected function DoPostRequestAuth($sRelativeUrl, $aData, $sLogin = 'admin', $sPassword = 'admin', $sOptionnalHeaders = null)
+	{
+		$aDataAndAuth = $aData;
+		$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)
+		{
+			throw new Exception("Problem with $sUrl, $php_errormsg");
+		}
+		$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 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);
+		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();
+
+	protected function DoPrepare()
+	{
+		MetaModel::Startup($this->GetConfigFile(), true); // Load model only
+// #@# Temporary disabled by Romain
+//		MetaModel::CheckDefinitions();
+
+		// something here to create records... but that's another story
+	}
+
+	protected $m_oChange;
+	protected function ObjectToDB($oNew, $bReload = false)
+	{
+		list($bRes, $aIssues) = $oNew->CheckToInsert();
+		if (!$bRes)
+		{
+			throw new CoreException('Could not create object, unexpected values', array('attributes' => $aIssues));
+		}
+		if ($oNew instanceof CMDBObject)
+		{
+			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; 
+			}
+			if ($bReload)
+			{
+				$iId = $oNew->DBInsertTracked($this->m_oChange);
+			}
+			else
+			{
+				$iId = $oNew->DBInsertTrackedNoReload($this->m_oChange);
+			}
+		}
+		else
+		{
+			if ($bReload)
+			{
+				$iId = $oNew->DBInsert();
+			}
+			else
+			{
+				$iId = $oNew->DBInsertNoReload();
+			}
+		}
+		return $iId;
+	}
+
+	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(DBObjectSearch $oMyFilter)
+	{
+		$oObjSet = new CMDBObjectSet($oMyFilter);
+		echo $oMyFilter->__DescribeHTML()."' - 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;
+	}
+}
+
+
+?>

+ 1 - 1
pages/ITopConsultant.php

@@ -433,7 +433,7 @@ if (empty($sConfigFile))
 	exit;
 }
 
-MetaModel::Startup($sConfigFile, true); // allow missing DB
+MetaModel::Startup($sConfigFile, true); // load data model only
 
 
 $sBaseArgs = "config=".urlencode($sConfigFile);

+ 7 - 6
setup/index.php

@@ -342,10 +342,10 @@ function CheckServerConnection(SetupWebPage $oP, $sDBServer, $sDBUser, $sDBPwd)
  * Helper function to initialize the ORM and load the data model
  * from the given file
  * @param $sConfigFileName string The name of the configuration file to load
- * @param $bAllowMissingDatabase boolean Whether or not to allow loading a data model with no corresponding DB 
+ * @param $bModelOnly boolean Whether or not to allow loading a data model with no corresponding DB 
  * @return none
  */    
-function InitDataModel(SetupWebPage $oP, $sConfigFileName, $bAllowMissingDatabase = true)
+function InitDataModel(SetupWebPage $oP, $sConfigFileName, $bModelOnly = true)
 {
 	require_once('../core/log.class.inc.php');
 	require_once('../core/coreexception.class.inc.php');
@@ -361,8 +361,9 @@ function InitDataModel(SetupWebPage $oP, $sConfigFileName, $bAllowMissingDatabas
 	require_once('../core/dbobjectsearch.class.php');
 	require_once('../core/dbobjectset.class.php');
 	require_once('../core/userrights.class.inc.php');
-	$oP->log("Info - MetaModel::Startup from file '$sConfigFileName' (AllowMissingDB = $bAllowMissingDatabase)");
-	MetaModel::Startup($sConfigFileName, $bAllowMissingDatabase);
+	$oP->log("Info - MetaModel::Startup from file '$sConfigFileName' (ModelOnly = $bModelOnly)");
+
+	MetaModel::Startup($sConfigFileName, $bModelOnly);
 }
 /**
  * Helper function to create the database structure
@@ -410,7 +411,7 @@ function CreateDatabaseStructure(SetupWebPage $oP, Config $oConfig, $sDBName, $s
 function CreateAdminAccount(SetupWebPage $oP, Config $oConfig, $sAdminUser, $sAdminPwd, $sLanguage)
 {
 	$oP->log('Info - CreateAdminAccount');
-	InitDataModel($oP, TMP_CONFIG_FILE, true);  // allow missing DB
+	InitDataModel($oP, TMP_CONFIG_FILE, true);  // load data model only
 	if (UserRights::CreateAdministrator($sAdminUser, $sAdminPwd, $sLanguage))
 	{
 		$oP->ok("Administrator account '$sAdminUser' created.");
@@ -943,7 +944,7 @@ function SetupFinished(SetupWebPage $oP, $aParamValues, $iCurrentStep, Config $o
 		$oConfig->WriteToFile(FINAL_CONFIG_FILE);
 
 		// Start the application
-		InitDataModel($oP, FINAL_CONFIG_FILE, false); // DO NOT allow missing DB
+		InitDataModel($oP, FINAL_CONFIG_FILE, false); // Load model and startup DB
 		if (UserRights::Login($sAuthUser, $sAuthPwd))
 		{
 			$_SESSION['auth_user'] = $sAuthUser;

+ 2 - 2
setup/xmldataloader.class.inc.php

@@ -85,7 +85,7 @@ class XMLDataLoader
 	/**
 	 * Initializes the ORM (MetaModel)
 	 */	 	
-	protected function InitDataModel($sConfigFileName, $bAllowMissingDatabase = true)
+	protected function InitDataModel($sConfigFileName)
 	{
 		require_once('../core/log.class.inc.php');
 		require_once('../core/coreexception.class.inc.php');
@@ -101,7 +101,7 @@ class XMLDataLoader
 		require_once('../core/dbobjectsearch.class.php');
 		require_once('../core/dbobjectset.class.php');
 		require_once('../core/userrights.class.inc.php');
-		MetaModel::Startup($sConfigFileName, $bAllowMissingDatabase);
+		MetaModel::Startup($sConfigFileName);
 	}
 	
 	/**