<?php

/*
 * @copyright NetMonsters <team@netmonsters.ru>
 * @link http://netmonsters.ru
 * @package Majestic
 * @subpackage UnitTests
 * @since 2011-11-7
 * 
 * Unit tests for MySQLiDriver class
 */

require_once dirname(__FILE__) . '/../../model/Db.php';
require_once dirname(__FILE__) . '/../../model/DbStatement.php';
require_once dirname(__FILE__) . '/../../model/MySQLiStatement.php';
require_once dirname(__FILE__) . '/../../model/DbDriver.php';
require_once dirname(__FILE__) . '/../../model/SqlDbDriver.php';
require_once dirname(__FILE__) . '/../../model/MySQLiDriver.php';
require_once dirname(__FILE__) . '/../../exception/GeneralException.php';

class MySQLiDriverTest extends PHPUnit_Extensions_Database_TestCase
{
    static private $pdo = null;

    private $conn = null;

    private $conf = array();



    protected function getConnection()
    {
        if ($this->conn === null) {
            if (self::$pdo == null) {
                self::$pdo = new PDO($GLOBALS['DB_DSN'], $GLOBALS['DB_USER'], $GLOBALS['DB_PASSWD']);
            }
            $this->conn = $this->createDefaultDBConnection(self::$pdo, $GLOBALS['DB_DBNAME']);
        }

        $this->conf = array('hostname' => 'localhost', 'database' => $GLOBALS['DB_DBNAME'], 'username' => $GLOBALS['DB_USER'], 'password' => $GLOBALS['DB_PASSWD']);

        return $this->conn;
    }

    protected function getDataSet()
    {
        return $this->createFlatXMLDataSet(dirname(__FILE__) . '/testData.xml');
    }

    public function run(PHPUnit_Framework_TestResult $result = NULL)
    {
        $this->setPreserveGlobalState(false);
        return parent::run($result);
    }
    /**
     * @group MySQL
     */
    public function testDriver()
    {
        Config::set('DEBUG', false);

        $driver = new MySQLiDriver($this->conf);

        $queryTable = $this->getConnection()->createQueryTable(
            'table', 'SELECT * FROM `table`'
        );
        $expectedTable = $this->createFlatXmlDataSet(dirname(__FILE__) . '/testData.xml')
                ->getTable("table");
        $this->assertTablesEqual($expectedTable, $queryTable);

        $this->assertSame(1, $driver->insert('table', array('id' => 3, 'user' => 'tony', 'content' => 'some test content', 'created' => '2011-11-07 11:35:20')));
        $this->assertSame(3, $this->getConnection()->getRowCount('table'));
    }
    /**
     * @group MySQL
     */
    public function testGetConnection()
    {
        Config::set('DEBUG', false);

        $driver = new MySQLiDriver($this->conf);
        $this->assertInstanceOf('mysqli', $driver->getConnection());
        $this->assertTrue($driver->isConnected());
    }
    /**
     * @group MySQL
     */
    public function testGetConnectionWrongConfig()
    {
        Config::set('DEBUG', false);
        $this->conf['database'] = 'nodb';
        $driver = new MySQLiDriver($this->conf);

        $this->setExpectedException('GeneralException', 'Unknown database \'nodb\'');

        $this->assertNull('mysqli', $driver->getConnection());
    }
    /**
     * @group MySQL
     */
    public function testDisconnect()
    {
        Config::set('DEBUG', false);

        $driver = new MySQLiDriver($this->conf);

        $driver->disconnect();
        $this->assertAttributeEquals(null, 'connection', $driver);

        $this->assertInstanceOf('mysqli', $driver->getConnection());
        $this->assertAttributeInstanceOf('mysqli', 'connection', $driver);
        $driver->disconnect();
        $this->assertAttributeEquals(null, 'connection', $driver);
    }
    /**
     * @group MySQL
     */
    public function testInsert()
    {
        Config::set('DEBUG', false);

        $driver = new MySQLiDriver($this->conf);
        
        $this->assertSame(1, $driver->insert('table', array('id' => 3, 'user' => 'tony', 'content' => 'some test content', 'created' => '2011-11-07 11:35:20')));
        $this->assertSame(3, $driver->getInsertId());
        $this->assertSame(1, $driver->insert('table', array('id' => null, 'user' => 'tony', 'content' => 'some test content', 'created' => '2011-11-07 11:35:20')));
        $this->assertSame(4, $driver->getInsertId());
        $this->assertSame(1, $driver->insert('table', array('id' => null, 'user' => true, 'content' => 'some test content', 'created' => '2011-11-07 11:35:20')));
        $this->assertSame(5, $driver->getInsertId());
        $this->assertSame(2, $driver->insert('table', array('id' => '5', 'user' => true, 'content' => 'some test content', 'created' => '2011-11-07 11:35:20'), array('id' => 8)));
        $this->assertSame(8, $driver->getInsertId());
    }

    /**
     * @TODO: DbDriver::getInsertId($table = null, $key = null) - params not used
     * @group MySQL
     */
    public function testGetInsertId()
    {
        Config::set('DEBUG', false);

        $driver = new MySQLiDriver($this->conf);

        $this->assertSame(1, $driver->insert('table', array('id' => 3, 'user' => 'tony', 'content' => 'some test content', 'created' => '2011-11-07 11:35:20')));
        $this->assertSame(3, $driver->getInsertId());
    }
    /**
     * @group MySQL
     */
    public function testTransaction()
    {
        Config::set('DEBUG', false);

        $driver = new MySQLiDriver($this->conf);

        $queryTable = $this->getConnection()->createQueryTable(
            'table', 'SELECT * FROM `table`'
        );
        $expectedTable = $this->createFlatXmlDataSet(dirname(__FILE__) . '/testData.xml')
                ->getTable("table");
        $this->assertTablesEqual($expectedTable, $queryTable);

        $driver->getConnection();
        $driver->beginTransaction();
        $driver->insert('table', array('id' => null, 'user' => 'tony', 'content' => 'some test content', 'created' => '2011-11-07 11:35:20'));
        $driver->insert('table', array('id' => null, 'user' => 'tony', 'content' => 'some test content', 'created' => '2011-11-07 11:35:20'));
        $driver->insert('table', array('id' => null, 'user' => 'tony', 'content' => 'some test content', 'created' => '2011-11-07 11:35:20'));
        $driver->insert('table', array('id' => null, 'user' => 'tony', 'content' => 'some test content', 'created' => '2011-11-07 11:35:20'));

        $queryTable = $this->getConnection()->createQueryTable(
            'table', 'SELECT * FROM `table`'
        );
        $driver->commit();
        $expectedTable = $this->createFlatXmlDataSet(dirname(__FILE__) . '/testDataAfterCommit.xml')
                ->getTable("table");
        $this->assertTablesEqual($expectedTable, $queryTable);
    }
    /**
     * @group MySQL
     */
    public function testRollback()
    {
        Config::set('DEBUG', false);

        $driver = new MySQLiDriver($this->conf);

        $queryTable = $this->getConnection()->createQueryTable(
            'table', 'SELECT * FROM `table`'
        );
        $expectedTable = $this->createFlatXmlDataSet(dirname(__FILE__) . '/testData.xml')
                ->getTable("table");
        $this->assertTablesEqual($expectedTable, $queryTable);

        $driver->getConnection();
        $driver->beginTransaction();
        $driver->insert('table', array('id' => null, 'user' => 'tony', 'content' => 'some test content', 'created' => '2011-11-07 11:35:20'));
        $driver->insert('table', array('id' => null, 'user' => 'tony', 'content' => 'some test content', 'created' => '2011-11-07 11:35:20'));
        $driver->insert('table', array('id' => null, 'user' => 'tony', 'content' => 'some test content', 'created' => '2011-11-07 11:35:20'));
        $driver->insert('table', array('id' => null, 'user' => 'tony', 'content' => 'some test content', 'created' => '2011-11-07 11:35:20'));
        $driver->rollback();
        $queryTable = $this->getConnection()->createQueryTable(
            'table', 'SELECT * FROM `table`'
        );
        $this->assertTablesEqual($expectedTable, $queryTable);
    }
}