<?php
/**
 * This file contains the PMO_Dbms_Sqlite driver class.
 *
 * This file is part of the PhpMyObject project,
 * an Object-Relational Mapping (ORM) system.
 * 
 * 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.15
 * @version			$Revision$
 * @copyright		Copyright (c) 2008 Louis Lapointe
 * @license			GPLv3 {@link http://www.gnu.org/licenses/gpl}
 * @filesource
 */ 

/**
 * setup the test cases if called individually
 */
if (!defined('PMO_TEST_SUITE')) {
	require_once(dirname(dirname(__FILE__)).DIRECTORY_SEPARATOR.'config.php');
	require_once(SIMPLETEST.DS.'autorun.php');
	require_once(PMO_TESTS . DS . 'simpletest' . DS . 'PMO_HTMLReporter.php');
}

/**
 * requires the libraries we want to test
 */
require_once(PMO_CORE . DS . 'PMO_MyDbms.php');
require_once(PMO_CORE . DS . 'PMO_Dbms_pdo.php');
require_once(PMO_CORE . DS . 'PMO_Dbms_Sqlite.php');

/**
 * This class tests the PMO_Dbms_Sqlite Connection.
 *
 * these are just sanity checks. Real testing is done
 * on PMO_MyDbms
 */
class PMO_Dbms_Sqlite_Connection_Test extends UnitTestCase 
{
   /** constructor calls parent contructor. */
   function PMO_Dbms_Sqlite_Connection_Test()
   {
      $this->UnitTestCase();
   }

   function setUp()
   {
   }

   function tearDown()
   {
   }

   function test_connect_with_bad_path()
   {
      $db = new PMO_Dbms_sqlite();
      $file = dirname(__FILE__).DS.'BAD_DIR'.DS.'test.db';
      $authdb = array('dsn' => 'sqlite:'.$file);

      try {
         $db->connect($authdb);
         $this->fail(file_exists($file), "The path $file does not exist. This should have thrown an exception!");
      }
      catch (PDOException $e) {
         $this->pass($e->getMessage().'. file $file does not exist. Connect threw a exception');
      }
   }


   function test_connect_good_connection()
   {
      $db = new PMO_Dbms_sqlite();
      $file = dirname(__FILE__). DS.'test.db';
      $authdb = array('dsn' => 'sqlite:'.$file);

      try {
         $db->connect($authdb);
         $this->assertTrue(file_exists($file), "The test database $file now exists");
      }
      catch (PDOException $e) {
         $this->fail($e->getMessage());
      }
      @unlink($file);
   }

}

/**
 * This tests the PMO_Dbms_Sqlite class.
 *
 * these are just sanity checks. Real testing is done
 * on PMO_MyDbms
 */
class PMO_Dbms_Sqlite_Test extends UnitTestCase 
{
   /** constructor calls parent contructor. */
   function PMO_Dbms_Sqlite_Test()
   {
      $this->UnitTestCase();
      $this->setSql();
   }

   function setUp()
	{
      $this->dbfile = dirname(__FILE__). DS .'test.db';
      $this->authdb['dsn'] = 'sqlite:'.$this->dbfile;

      $this->db = new PMO_Dbms_Sqlite();
      $this->db->connect($this->authdb);
		$this->db->query($this->drop);
      $this->db->query($this->create);

      foreach ($this->inserts as $insert) {
         $sql = 'INSERT INTO `t1` VALUES ' . $insert;
         $this->db->query($sql);
      }
   }

   function tearDown()
   {
		//$this->db->query($this->drop);
      unset($this->db);
   }

   // helpers
   function setSql()
   {
		$this->drop = 'DROP TABLE IF EXISTS `t1`';
      $this->create = 'CREATE TABLE IF NOT EXISTS `t1` ('
                . '`id` INTEGER PRIMARY KEY AUTOINCREMENT,'
                . '`name` TEXT NOT NULL,'
                . '`group_id` INTEGER NOT NULL,'
                . '`description` TEXT DEFAULT NULL,'
                . '`start_date` DATE DEFAULT NULL'
                . ')' ;

      $this->inserts = array(
                   '(1, "one", 1, null, null)'
                  ,'(2, "two", 1, null, null)'
                  ,'(3, "three", 1, "description of three", "2008-02-29")'
                  ,'(4, "four", 10, null, null)'
                  ,'(5, "five", 10, null, null)'
                  ,'(6, "six", 10, null, null)'
                  ,'(7, "seven", 20, null, null)'
                  ,'(8, "eight", 20, null, null)'
                  ,'(9, "nine", 20, null, null)'
               );

   }


   function test_query()
   {
      $sql = 'select * from t1';
      $this->assertTrue($this->db->query($sql), 'select data that exists');

      try {
         $sql2 = $sql . ' where groups = "40"';
         $this->db->query($sql2);
         $this->fail('should have caught the exception since the column do not exist');
      }
      catch (Exception $e) {
         $this->assertWantedPattern('/no such column: groups/', $e->getMessage(), $e->getMessage());
      }

      $sql2 = $sql . ' where group_id = 40';
      $this->assertTrue($this->db->query($sql2), 'a select with nonexistent group_id');
   }

   function test_fetchArray()
   {
      $sql = 'select * from t1 where group_id = 1';
      $this->assertTrue($this->db->query($sql), "query [$sql] succeeded");

      $row = $this->db->fetchArray();
      $this->assertEqual(count($row), 5, 'the row does contain 5 columns');
      $this->assertEqual($row['name'], 'one', 'the first row[name] does equal "one"');

      $row = $this->db->fetchArray();
      $this->assertEqual($row['name'], 'two', 'the second row[name] does equal "two"');

      $row = $this->db->fetchArray();
      $this->assertEqual($row['id'], 3, 'the third row[id] does equal 3');
      $this->assertEqual($row['name'], 'three', 'the third row[name] does equal "three"');
      $this->assertEqual($row['group_id'], 1, 'the third row[group_id] does equal 1');
      $this->assertEqual($row['description'], 'description of three', 'the third row[description] does equal "description of three"');
      $this->assertEqual($row['start_date'], '2008-02-29', 'the third row[start_date] does equal "2008-02-29"');

      $row = $this->db->fetchArray();
      $this->assertFalse($row, 'there are no more rows');
   }

   function test_getTableDesc()
   {
		try {
	      $arr = $this->db->getTableDesc('t1');
		}
		catch(Exception $e) {
			$this->fail($e->getMessage());
			exit;
		}
      $this->assertTrue(is_array($arr), 'getTableDesc(t1) returned an array');
      $this->assertEqual(count($arr), 5, 'and returned 5 columns as expected');
      $this->assertEqual($arr[0]['Field'], 'id', 'Field value is "id" as expected');
      $this->assertEqual($arr[0]['Null'], 'NO', 'Null equals "NO" as expected');
      $this->assertEqual($arr[0]['Key'], 'PRI', 'Key contains "PRI" as expected');
      $this->assertEqual($arr[0]['Default'], '', 'Default is empty as expected');
      $this->assertEqual($arr[0]['Extra'], 'auto_increment', 'Extra contains "auto_increment" as expected');
      $this->assertEqual($arr[0]['Perm'], 'rw', 'Perm contains "rw" as expected');
   }

   function test_getLastId()
   {
      $now = date('Y-m-d H:i:s');
      $sql = "insert into `t1` values (null, 'last one', 99, 'a short description', '$now')";
      $this->db->query($sql);
      $this->assertEqual($this->db->getLastId(), 10, 'New id equals 10 as expected');
   }

	function test_transaction_commit() {
		$insert98 = 'INSERT INTO `t1` VALUES (98, "quatre-vingt dix-huit", 1,null,null)';
		$select98 = 'SELECT * FROM `t1` WHERE id = 98';

		$this->db->beginTransaction();
		$this->db->query($insert98);
		$this->db->commit();
		$this->db->query($select98);
		$res = $this->db->fetchArray();
		$this->assertEqual($res['id'], 98);

	}

	function test_transaction_rollback() {
		$insert99 = 'INSERT INTO `t1` VALUES (99, "quatre-vingt dix-neuf", 1,null,null)';
		$select99 = 'SELECT * FROM `t1` WHERE id = 99';

		$this->db->beginTransaction();
		$this->db->query($insert99);
		$this->db->rollback();
		$this->db->query($select99);
		$res = $this->db->fetchArray();
		$this->assertEqual($res['id'],NULL);
	}
}

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

	$test = new TestSuite('Sqlite Tests');
	$test->add(new PMO_Dbms_Sqlite_Connection_Test);
	$test->add(new PMO_Dbms_Sqlite_Test);
	$test->run(new PMO_HTMLReporter($level));
}

