<?php
/**
 * This file contains the PMO_MyDbms_Mysql tests.
 *
 * This file is part of the PhpMyObject project,
 * an Object-Relational Mapping (ORM) system.
 * 
 * Copyright (c) 2008 Louis Lapointe
 *
 * For questions, help, comments, discussion, etc., please join our
 * forum at {@link http://www.developpez.net/forums/forumdisplay.php?f=770} 
 *
 * PhpMyObject 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, either version 3 of the License, or
 * (at your option) any later version.
 *
 * 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, see {@link http://www.gnu.org/licenses/}.
 *
 * @package			PhpMyObject
 * @subpackage		PMO_Tests
 * @author			Louis Lapointe <laplix@gmail.com>
 * @link				http://pmo.developpez.com/
 * @since			PhpMyObject v0.16
 * @version			$Revision$
 * @copyright		Copyright (C) 2008 Louis Lapointe
 * @license			GPLv3 {@link http://www.gnu.org/licenses/gpl}
 * @filesource
 *
 */ 

/**
 * setup this test case if called individually
 */
if (!defined('PMO_TEST_SUITE')) {
	require_once(dirname(dirname(__FILE__)).DIRECTORY_SEPARATOR.'config.php');
	require_once(SIMPLETEST.DS.'autorun.php');
}


/**
 * requires the PMO_MyDbms file.
 */
require_once(PMO_CORE . DS . 'PMO_MyDbms.php');

/**
 * loads the Html reporter
 */
require_once(PMO_TESTS . DS . 'simpletest' . DS . 'PMO_HTMLReporter.php');

/**
 * This tests the PMO_MyDbms class.
 *
 */
class PMO_MyDbms_Mysql_Test extends UnitTestCase
{

	/**
	 * constructor calls parent contructor
	 */
	function __constuct() {
		$this->UnitTestCase();
	}

	/**
	 * this gets called before each test
	 */
	function setUp() {
		$config = PMO_MyConfig::factory();
		$config->set('PMO_MyDbms.DRIVER','mysql');
		$config->set('PMO_MyDbms.PDODRIVER', '');
		$config->set('PMO_MyDbms.HOST','localhost');
		$config->set('PMO_MyDbms.USER','pmo');
		$config->set('PMO_MyDbms.PASS','pmo');
		$config->set('PMO_MyDbms.BASE','sakila');
		$config->set('PMO_MyDbms.DSN','');
		$config->set('PMO_MyDbms.LOG', TRUE);
		PMO_MyLog::factory()->start();
	}

	/**
	 * this method is called after each test
	 */
	function tearDown() {
		PMO_MyDbms::factory()->killInstance();
	}

	/**
	 * helper function build table nico in database pmo_test
	 */
	function reset_pmo_test_table_nico() {
		$config = PMO_MyConfig::factory();
		$config->set('PMO_MyDbms.DRIVER','mysql');
		$config->set('PMO_MyDbms.PDODRIVER', '');
		$config->set('PMO_MyDbms.HOST','localhost');
		$config->set('PMO_MyDbms.USER','pmo');
		$config->set('PMO_MyDbms.PASS','pmo');
		$config->set('PMO_MyDbms.BASE','pmo_test');
		$config->set('PMO_MyDbms.DSN','');

		$dbms = PMO_MyDbms::factory();
		$sql = 'DROP TABLE IF EXISTS nico';
		$dbms->query($sql);

		$sql = 'CREATE TABLE IF NOT EXISTS nico (';
		$sql .= 'id int unsigned not null auto_increment';
		$sql .= ',nom varchar(60) not null';
		$sql .= ',primary key (id) ) engine=InnoDB';

		$dbms->query($sql);
	}

	/**
	 * helper function build table nico in pmo_test database
	 * and  fills ut with 4 rows
	 */
	function reset_and_fill_pmo_test_table_nico() {
		$this->reset_pmo_test_table_nico();
		$dbms = PMO_MyDbms::factory();

		// insert a few rows
		$dbms = PMO_MyDbms::factory();
		$dbms->query("INSERT INTO nico VALUES(1, 'line1')");
		$dbms->query("INSERT INTO nico VALUES(2, 'line2')");
		$dbms->query("INSERT INTO nico VALUES(3, 'line3')");
		$dbms->query("INSERT INTO nico VALUES(0, 'line4')");
	}

	//
	// tests start here
	//

	function test_factory_returns_a_PMO_Dbms_object() {
		$dbms = PMO_MyDbms::factory();
		$this->assertTrue($dbms instanceof PMO_Dbms, 'is an instance of PMO_Dbms');
		$this->assertTrue($dbms instanceof PMO_MyDbms, 'is an instance of PMO_MyDbms');
		$this->assertTrue($dbms instanceof PMO_Dbms_Mysql,'is an instance of PMO_Dbms_Mysql');
	}

	function test_object_has_resource() {
		$dbms = PMO_MyDbms::factory();
		$this->assertTrue(is_resource($dbms->getDB()) ,'->getDB() returns a resource');
	}
		
	function test_killInstance() {
		PMO_MyLog::factory()->log('running test_killInstance()');
		$dbms = PMO_MyDbms::factory();
		$this->assertTrue(is_resource($dbms->getDB()) ,'before killInstance, ->getDB() returns a resource');
		$dbms->killInstance();
		$this->assertFalse(is_resource($dbms->getDB()) ,'after killInstance, ->getDB() does not return a resource anymore');
		try {
			$dbms->query('SELECT * FROM actor LIMIT 1');
			$this->fail('After a killInstance, a query should throw an exception!!');
		}
		catch (Exception $e) {
			$this->assertEqual('No connection available!', $e->getMessage());
		}
	}

	function test_simple_query() {
		PMO_MyLog::factory()->log('after test_killInstance()');
		$dbms = PMO_MyDbms::factory();
		$result = $dbms->query('SELECT * FROM actor where actor_id = 1');
		$this->assertTrue($result, 'select existing data');
		$result = $dbms->query('SELECT * FROM actor where actor_id = 500');
		$this->assertTrue($result, 'select non-existant data');
	}

	function test_load_data_from_object() {
		$dbms = PMO_MyDbms::factory();
		$obj = PMO_MyObject::factory('actor');
		$obj->actor_id = 11;
		$dbms->load($obj);
		$this->assertEqual($obj->first_name, 'ZERO', 'load existing data');
		unset($obj);
		$obj = PMO_MyObject::factory('actor');
		$obj->actor_id = 500;
		try {
			$dbms->load($obj);
		}
		catch(Exception $e) {
		$this->assertPattern('/can not be found/', $e->getMessage());
		}
	}

	function test_insert() {
		$this->reset_pmo_test_table_nico();

		$dbms = PMO_MyDbms::factory();

		// insert a few rows
		$dbms->query("INSERT INTO nico VALUES(500, 'line 500')");
		$dbms->query("INSERT INTO nico VALUES(501, 'line 501')");
		$dbms->query("INSERT INTO nico VALUES(502, 'line 502')");
		$dbms->query("INSERT INTO nico VALUES(0,   'line 503')");


		$nico = PMO_MyObject::factory('nico');
		$nico->id = 500;
		$dbms->load($nico);
		$this->assertEqual($nico->nom, 'line 500');

		unset ($nico);
		$nico = PMO_MyObject::factory('nico');
		$nico->nom = 'line 503';
		$nico->load();
		$this->assertEqual($nico->id, 503);

	}

	function test_delete() {
		$this->reset_and_fill_pmo_test_table_nico();

		$dbms = PMO_MyDbms::factory();
		$nico = PMO_MyObject::factory('nico');
		$nico->id = 1;
		$dbms->delete($nico);

		unset($nico);
		$nico = PMO_MyObject::factory('nico');
		$nico->id = 1;
		try {
			$dbms->load($nico);
		}
		catch(Exception $e) {
			$this->assertPattern('/can not be found/', $e->getMessage());
		}
	}

	function test_update() {
		$this->reset_and_fill_pmo_test_table_nico();
		$dbms = PMO_MyDbms::factory();

		$nico = PMO_MyObject::factory('nico');
		$nico->id = 1;
		$dbms->load($nico);
		$this->assertEqual($nico->nom, 'line1', 'before update, nom = '.$nico->nom);

		$nico->nom = 'has a new line 1';
		$dbms->update($nico);

		unset ($nico);
		$nico = PMO_MyObject::factory('nico');
		$nico->id = 1;
		$dbms->load($nico);
		$this->assertEqual($nico->nom, 'has a new line 1', 'after update nom = '.$nico->nom);

	}

	function test_transactions() {
		$this->reset_and_fill_pmo_test_table_nico();
		$dbms = PMO_MyDbms::factory();

		$nico = PMO_MyObject::factory('nico');
		$nico->id = 2;
		$dbms->load($nico);
		$this->assertEqual($nico->nom, 'line2', 'avant update nom = '. $nico->nom);
		$nico->nom = 'has a new line 2';
		$dbms->beginTransaction();
		$dbms->update($nico);
		$dbms->commit();

		$nico = PMO_MyObject::factory('nico');
		$nico->id = 2;
		$dbms->load($nico);
		$this->assertEqual($nico->nom, 'has a new line 2', 'after commit nom = '.$nico->nom);

		unset ($nico, $dbms);
		$nico = PMO_MyObject::factory('nico');
		$dbms = PMO_MyDbms::factory();

		$nico->id = 3;
		$dbms->load($nico);
		$this->assertEqual($nico->nom, 'line3', 'avant update nom = '.$nico->nom);
		$nico->nom = 'has a new line 3';
		$dbms->beginTransaction();
		$dbms->update($nico);
		$dbms->rollback();

		$nico = PMO_MyObject::factory('nico');
		$nico->id = 3;
		$dbms->load($nico);
		$this->assertEqual($nico->nom, 'line3', 'after rollback nom = '.$nico->nom);

	}

	function test_logging_function() {
		$config = PMO_MyConfig::factory();
		$config->set('PMO_MyDbms.LOG',true);
		$dbms = PMO_MyDbms::factory();
		$dbms->setLog('Hello World');
		$dbms->setLog('Here is PMO');

		$dbms = PMO_MyDbms::factory();
		$obj = PMO_MyObject::factory('actor');
		$obj->actor_id = 11;
		$dbms->load($obj);

		$log  = $dbms->getLog();
		$config->set('PMO_MyDbms.LOG',false);

		$this->assertIsA($log, 'array',print_r($log,true));
		$this->assertEqual(count($log), 3, 'Un log activé devrait enregistrer le SQL exécuté');
		$this->assertPattern('/Hello World/', $log[0]);
	}

}

// run the tests if called individually
if (!defined('PMO_TEST_SUITE')) {
	$level = '';
	if (isset($_COOKIE['testLevel'])) {
		$level = $_COOKIE['testLevel'];
		setcookie('testLevel', $level, time()+60*60*24*30);
	}
	elseif (isset($_GET['level'])) {
		$level = $_GET['level'];
		setcookie('testLevel', $level, time()+60*60*24*30);
	}

	$test = new TestSuite('DBMB MySQL Tests');
	$test->add(new PMO_MyDbms_Mysql_Test);
	$test->run(new PMO_HTMLReporter($level));
}

