<?php

/**
 * Test suite that checks the database structure if basic operations can be performed on the database
 * (Insert, delete, select)
 * 
 * @author jmosshammer <jannis.mosshammer@netways.de>
 *
 */

/**
* @depends agaviBootstrapTest::testBootstrap 
*/	
class icingaDatabaseAccessibleTest extends PHPUnit_Framework_TestCase {
	private $properties = array();
	private $insertFailed = false;
	
	private static $dbTestEntries =array(
		array("model"=>"NsmRole",
			"fields"=>array(
				"role_name"=>"TestCaseRole",
				"role_description" => "Role generated by PHPUnit",
				"role_disabled" => 0
			),
			"toProp" => "lastRole"
		),
		
		array("model"=>"NsmUser",
			"fields"=>array(
				"user_name" => "TestCaseUser",
				"user_account" => 0,
				"user_disabled" => 0,
				"user_firstname" => "TestCase",
				"user_lastname"=> "TesvtCase",
				"user_password" => "test123",
				"user_salt" => "dsgdgd",
				"user_authsrc" => "internal",
				"user_email" => "test@testuser.local"
			),
			"toProp" => "lastUser"
		),
		
		array("model"=>"NsmTarget",
			"fields"=>array(
				"target_name" => "TestCase",
				"target_description" => "TestCase-Target",
				"target_class" => "TestCaseClass",
				"target_type" => "credential"
			),
			"toProp" => "lastTarget"
		),
		
		array("model" => "NsmPrincipal",
			"fields" => array(
				"principal_type" =>  'role',
				"principal_disabled" => 0,
			),
			"toProp" => "lastPrincipal_User"
		),
		
		array("model" => "NsmPrincipal",
			"fields" => array(
				"principal_type" => 'user',
				"principal_disabled" => 0,
			),
			"toProp" => "lastPrincipal_Role"
		),
	
		array("model"=>"NsmSession",
			"fields"=>array(
				"session_id"=>"TestCaseID",
				"session_name" => "Testcase",
				"session_data" => "TESTCASE DATA STREAM",
				"session_checksum" => "1b8e97d364c6f7a6a600a00b203cfd34"
			)
		),
		
		array("model"=>"NsmLog",
			"fields" => array(
				"log_level" => 0,
				"log_message" => "TestCase speaking!",
			)
		)
	);
	/**
	 * 
	 */
    /** 
     * @group Database
     */
	public function testAvailable() {
		info("Testing accessibility\n");
		Doctrine_Manager::connection()->beginTransaction();
		
		foreach(Doctrine::getLoadedModels() as $model) {
		    
		    if (strpos($model, 'Doctrine_File') !== false) {
		        continue;
		    }
		    
			info("\tChecking table for ".$model."... \n");
			try {
				$result = Doctrine_Query::create()->select("*")->from($model)->execute();
				$this->assertNotNull($result,"Result returned null!");
			} catch(Exception $e) {
				$this->fail("Table for Doctrinemodel ".$model." not found (".$e->getMessage().")");
			}		
		}
		return true;
	}
	
	/**
	 * @depends testAvailable
	 * @group Database
	 */
	public function testInsert() {
		
		info("Insert tests\n");
		foreach(self::$dbTestEntries as &$entry) {
			$model = $entry["model"];
			$fields = $entry["fields"];
			try {
				info("\tInserting data in ".$model." \n");
				if(!class_exists($model))
					$this->fail("Couldn't find class ".$model);
				$dbRecord = new $model();
				foreach($fields as $name=>&$field) {
					$dbRecord->set($name,$field);
				}
				$dbRecord->save();
				$id = $dbRecord->identifier();
				$key = array_keys($id);
				$entry["__ID"] = array($key[0],$id[$key[0]]);
			} catch(Exception $e) {
				$this->fail($e->getMessage());
			}
		}
		return true;
	}

	/**
	 * @depends testInsert
	 * @group Database
	 */
	public function testDataEquality() {
		info("Checking inserted data\n");
		$entries = self::$dbTestEntries;
		foreach($entries as $entry) {
			$model = $entry["model"];
			$fields = $entry["fields"];
			$dbmodel = Doctrine::getTable($model)->findBy($entry["__ID"][0],$entry["__ID"][1])->getFirst();
			$this->assertNotNull($dbmodel,"The entry for ".$model." could not be found");
			foreach($fields as $field=>$value) {
				$this->assertEquals($dbmodel->get($field),$value,"The value for field ".$field." in ".$model." differs from the initial value!");
			}
		}
		return true;
	}
	
	/**
	 * @depends testDataEquality
	 * @depends testInsert
	 * @group Database
	 */
	public function testRemove() {
		info("Test delete operation\n");
		$entries = self::$dbTestEntries;
		foreach($entries as $entry) {
			$model = $entry["model"];
			$fields = $entry["fields"];
			$dbmodel = Doctrine::getTable($model)->findBy($entry["__ID"][0],$entry["__ID"][1])->getFirst();
			$this->assertNotNull($dbmodel,"The entry for ".$model." could not be found");
			$dbmodel->delete();
		}
		// check if they are really removed
		foreach($entries as $entry) {
			$model = $entry["model"];
			$fields = $entry["fields"];
			$dbmodel = Doctrine::getTable($model)->findBy($entry["__ID"][0],$entry["__ID"][1])->getFirst();
			$this->assertFalse($dbmodel,"The entry for ".$model." should be removed");
		}
		return $entries;
	}

    /** 
    * @group Database
    */
	public function doctrineModelProvider()	{
		$models = Doctrine::getLoadedModels();
    	foreach($models as &$model) {
    		$model = array($model);
    	}
    	return $models;
	}
	
    /** 
    * @group Database
    */
	public function testRollback() {
		Doctrine_Manager::connection()->rollback();
	}
	
}
