<?php

require_once dirname(__FILE__) . '/../../../prods/src/RODSAccount.class.php';
require_once dirname(__FILE__) . '/../../../prods/src/RODSConn.class.php';
require_once dirname(__FILE__) . '/../../../prods/src/RODSConnManager.class.php';
// require_once dirname(__FILE__) . '/../../../prods/src/ProdsConfig.inc.php';
require_once dirname(__FILE__) . '/../../../prods/src/ProdsPath.class.php';
require_once dirname(__FILE__) . '/../../../prods/src/ProdsDir.class.php';
require_once dirname(__FILE__) . '/../../../prods/src/RODSException.class.php';
require_once dirname(__FILE__) . '/../../../prods/src/RODSDirStats.class.php';
require_once dirname(__FILE__) . '/stubProdsDir.class.php';

/**
 * Test class for RODSAccount.
 * Generated by PHPUnit on 2011-02-24 at 16:39:16.
 */
class RODSAccountTest extends PHPUnit_Framework_TestCase {

    /**
     * @var RODSAccount
     */
    protected $rodsAcct;
    protected $id = "1";
    protected $name = "me";
    protected $zone = "myZone";
    protected $host = "myirods.myhost.mycom";
    protected $port = "1111";
    protected $passwd = "meme";
    protected $type = "rodsuser";
    protected $ctime = "01298479459";
    protected $mtime = "01298479459";
    protected $comment = "foo";
    protected $info = "bar";
    protected $dn = "";
    protected $resc = "demo";
    protected $auth_type = "irods";
    protected $ticket = "myticket";

    /**
     * Sets up the fixture, for example, opens a network connection.
     * This method is called before a test is executed.
     */
    protected function setUp() {
        $this->rodsAcct = new RODSAccount(
                $this->host,
                $this->port,
                $this->name,
                $this->passwd,
                $this->zone,
                $this->resc,
                $this->auth_type,
                $this->ticket);
    }

    /**
     * Tears down the fixture, for example, closes a network connection.
     * This method is called after a test is executed.
     */
    protected function tearDown() {
        unset($this->rodsAcct);
    }

    /**
     * @todo Implement testFromURI().
     */
    public function testFromURI() {
        // empty uri
        $this->rodsAcct = $this->rodsAcct->fromURI("");
        $this->assertEquals("", $this->rodsAcct->user);

        //invalid format uri
        $this->rodsAcct = $this->rodsAcct->fromURI("wrongformat");
        $this->assertEquals("", $this->rodsAcct->user);

        //valid uri
        $this->rodsAcct = $this->rodsAcct->fromURI("notme.myZone@myirods.myhost.mycom:1111/myZone/home/notme");
        $this->assertEquals("notme", $this->rodsAcct->user);
    }

    /**
     * @todo Implement testEquals().
     */
    public function testEquals() {

        $newAcct = new RODSAccount("another_irods.notmyhost.mmm", "1112", "notme", "mememe", "notmyZone");
        $this->assertEquals(FALSE, $this->rodsAcct->Equals($newAcct));

        $newAcct = new RODSAccount($this->host, $this->port, $this->name, $this->passwd, $this->zone);
        $this->assertEquals(TRUE, $this->rodsAcct->Equals($newAcct));
    }

    /**
     * @todo Implement testGetSignature().
     */
    public function testGetSignature() {
        
        // test_ret value should be 'd84456497b1b340d8f4f751d36fd2d8d'
        $expected_ret = bin2hex(md5("$this->name.$this->zone:this->pass@$this->host:$this->port.$this->ticket", TRUE));
        $actual_ret = $this->rodsAcct->getSignature();
        //$this->assertEquals($expected_ret, $actual_ret, TRUE);
        $this->assertEquals($expected_ret, $actual_ret);
    }

    /**
     * @todo Implement test__toString().
     */
    public function test__toString() {
        $expected = $this->name . "." . $this->zone . ":(password hidden)@" . $this->host . ":" . $this->port;
        //$this->assertEquals("me.myZone:(password hidden)@myirods.myhost.mycom:1111", $this->rodsAcct->__toString());
        $this->assertEquals($expected, $this->rodsAcct->__toString());
    }

    /**
     * @todo Implement testToURI().
     */
    public function testToURI() {
        $expected = $this->name . "." . $this->zone . "@" . $this->host . ":" . $this->port;
        //$this->assertEquals($this->rodsAcct->toURI(), "me.myZone@myirods.myhost.mycom:1111");
        $this->assertEquals($expected, $this->rodsAcct->toURI());
        // also add test for when zone is empty
    }

    /**
     * @todo Implement testGetUserInfo().
     */
    public function testGetUserInfo() {


        $this->markTestIncomplete(
                'This test has not been implemented yet.'
        );

        // THIS TEST NEEDS TO BE FIXED - it causes a segmentation violation on Hudson (different PHP version?)
        // No RODSConnMOck defined? Or perhaps need to use stubRODSConn instead

        // set up mock parameters
        $retval = stubGetUserInfo();
        $mocked_rodsconn_methods = array('getUserInfo');
        $mocked_rodsconn_construct_params = array(&$this->rodsAcct);

        $mocked_rodsaccount_methods = array('getRODSConnection');
        $mocked_rodsaccount_construct_params = array($this->host, $this->port, $this->name, $this->passwd, $this->zone);

        // need to stub out RODSAccount methods getRODSConnection and releaseRODSConnection
        // getRODS connection stub must return mocked RODSConn object

        // first mock RODSConn
        $conn_stub = $this->getMock('RODSConn', $mocked_conn_methods, $mocked_rodsconn_construct_params, 'RODSConnMock');
        $conn_stub->expects($this->any())->method('getUserInfo')->will($this->returnValue($retval));

        $acct_stub = $this->getMock('RODSAccount', $mocked_rodsaccount_methods, $mocked_rodsaccount_construct_params, 'RODSAccountMock');
        $acct_stub->expects($this->any())->method('getRODSConnection')->will($this->returnValue($conn_stub));

        // now setup mock for RODSConnManager
        //$conn_mgr_stub = $this->getMock('RODSConnManager', $mocked_rodsconnmanager_methods, $mocked_rodsconnmanager_construct_params, 'RODSConnManagerMock');
        //$conn_mgr_stub->staticExpects($this->any())->method('getConn')->with($mocked_rodsconnmanager_getconn_params)->will($this->returnValue($retval));

        //set up overload for constructors
        set_new_overload(array($this, 'newCallback'));

        // now run actual tests
        //var_dump($acct_stub);
        $this->assertEmpty($acct_stub->getRODSConnection());

        unset_new_overload();
    }

    /**
     * @todo Implement testGetTempPassword().
     */
    public function testGetTempPassword() {
        // Remove the following lines when you implement this test.
        $this->markTestIncomplete(
                'This test has not been implemented yet.'
        );
    }

    /**
     * @todo Implement testGetUserHomeDir().
     */
    public function testGetUserHomeDir() {

        $this->markTestIncomplete(
                'This test has not been implemented yet.'
        );

        // THIS TEST NEEDS TO BE FIXED - it causes a segmentation violation on Hudson (different PHP version?)
        // No RODSConnMOck defined? Or perhaps need to use stubRODSConn instead

        // need to get fake info from getUserInfo()
        // test with/without $init_path set
        // need to Mock ProdsDir and method exists()
        // ProdsDir has 2 constructor args:
        // (RODSAccount &$account, $path_str, $verify=false, RODSDirStats $stats=NULL)

        // set up mock parameters
        $retval = $this->stubGetUserInfo();
        $mocked_rodsacct_methods = array('getUserInfo');
        $mocked_rodsacct_construct_params = array($this->host, $this->port, $this->name, $this->passwd, $this->zone);


        $acct_stub = $this->getMock('RODSAccount', $mocked_rodsacct_methods, $mocked_rodsacct_construct_params);
        $acct_stub->expects($this->once())->method('getUserInfo')->will($this->returnValue($retval));

        //set up overload for constructors
        set_new_overload(array($this, 'newCallback'));

        // now run actual tests
        // test null zone code path and init_zone not set
        $acct_stub->zone = null;
        $p = $acct_stub->getUserHomeDir();
        $this->assertEquals("//home/". $this->name, $p->path_str);

        // test what path is taken when zone is not null and when init_path is set
        $acct_stub->expects($this->never())->method('getUserInfo')->will($this->returnValue($retval));
        $acct_stub->zone = $this->zone;
        $init_val = "/thiszone/testhome/me";
        $p = $acct_stub->getUserHomeDir($init_val);
        $this->assertEquals($init_val, $p->path_str);

        unset_new_overload();

    }

    /**
     * @todo Implement testGetUserHomeDirURI().
     */
    public function testGetUserHomeDirURI() {

        $this->markTestIncomplete(
                'This test has not been implemented yet.'
        );

        // THIS TEST NEEDS TO BE FIXED - it causes a segmentation violation on Hudson (different PHP version?)
        // No RODSConnMOck defined? Or perhaps need to use stubRODSConn instead

        // set up mock parameters
        $retval = $this->stubGetUserInfo();
        $mocked_rodsacct_methods = array('getUserInfo');
        $mocked_rodsacct_construct_params = array($this->host, $this->port, $this->name, $this->passwd, $this->zone);


        $acct_stub = $this->getMock('RODSAccount', $mocked_rodsacct_methods, $mocked_rodsacct_construct_params);
        $acct_stub->expects($this->any())->method('getUserInfo')->will($this->returnValue($retval));

        //set up overload for constructors
        set_new_overload(array($this, 'newCallback'));

        // now run actual tests
        $p = $acct_stub->getUserHomeDirURI();
        $expected = $this->name . "." . $acct_stub->zone . "@" . $acct_stub->host . ":" . $acct_stub->port . "/" . $acct_stub->zone . "/home/" . $acct_stub->user;
        $this->assertEquals($expected, $p);

        $init_val = "/thiszone/testhome/me";
        $p = $acct_stub->getUserHomeDirURI($init_val);
        $expected = $this->name . "." . $acct_stub->zone . "@" . $acct_stub->host . ":" . $acct_stub->port . $init_val;
        $this->assertEquals($expected, $p);

        unset_new_overload();

    }

    /**
     * @todo Implement testGetUserTrashDir().
     */
    public function testGetUserTrashDir() {

        $this->markTestIncomplete(
                'This test has not been implemented yet.'
        );

        // THIS TEST NEEDS TO BE FIXED - it causes a segmentation violation on Hudson (different PHP version?)
        // No RODSConnMOck defined? Or perhaps need to use stubRODSConn instead

        // set up mock parameters
        $retval = $this->stubGetUserInfo();
        $mocked_rodsacct_methods = array('getUserInfo');
        $mocked_rodsacct_construct_params = array($this->host, $this->port, $this->name, $this->passwd, $this->zone);


        $acct_stub = $this->getMock('RODSAccount', $mocked_rodsacct_methods, $mocked_rodsacct_construct_params);
        $acct_stub->expects($this->once())->method('getUserInfo')->will($this->returnValue($retval));

        //set up overload for constructors
        set_new_overload(array($this, 'newCallback'));

        // now run actual tests
        // test getUserInfo() is called when zone is null
        $acct_stub->zone = null;
        $p = $acct_stub->getUserTrashDir();
        $this->assertInstanceOf("stubProdsDir", $p);
        $this->assertEquals("//trash/home/" . $acct_stub->user, $p->path_str);

        // test what path is taken when zone is not null
        $acct_stub->zone = $this->zone;
        $acct_stub->expects($this->never())->method('getUserInfo')->will($this->returnValue($retval));
        $p = $acct_stub->getUserTrashDir();
        $this->assertInstanceOf("stubProdsDir", $p);
        $this->assertEquals("/" . $acct_stub->zone . "/trash/home/" . $acct_stub->user, $p->path_str);

        unset_new_overload();
    }

    /**
     * @todo Implement testGetUserTrashDirURI().
     */
    public function testGetUserTrashDirURI() {

        $this->markTestIncomplete(
                'This test has not been implemented yet.'
        );

        // THIS TEST NEEDS TO BE FIXED - it causes a segmentation violation on Hudson (different PHP version?)
        // No RODSConnMOck defined? Or perhaps need to use stubRODSConn instead

        // set up mock parameters
        $retval = $this->stubGetUserInfo();
        $mocked_rodsacct_methods = array('getUserInfo');
        $mocked_rodsacct_construct_params = array($this->host, $this->port, $this->name, $this->passwd, $this->zone);


        $acct_stub = $this->getMock('RODSAccount', $mocked_rodsacct_methods, $mocked_rodsacct_construct_params);
        $acct_stub->expects($this->once())->method('getUserInfo')->will($this->returnValue($retval));

        //set up overload for constructors
        set_new_overload(array($this, 'newCallback'));

        // now run actual tests
        $acct_stub->zone = null;
        $p = $acct_stub->getUserTrashDirURI();
        $expected = $acct_stub->user . "@" . $acct_stub->host . ":" . $acct_stub->port . "//trash/home/" . $acct_stub->user;
        $this->assertEquals($expected, $p);

        // noew test with zone set - getUserInfo() should never be called
        $acct_stub->zone = $this->zone;
        $acct_stub->expects($this->never())->method('getUserInfo')->will($this->returnValue($retval));
        $p = $acct_stub->getUserTrashDirURI();
        $expected = $acct_stub->user . "." . $acct_stub->zone . "@" . $acct_stub->host . ":" . $acct_stub->port . "/" . $acct_stub->zone . "/trash/home/" . $acct_stub->user;
        $this->assertEquals($expected, $p);

        unset_new_overload();

    }

    protected function newCallback($className) {
        switch($className) {
            case 'RODSConn': return RODSConnMock;
            case 'ProdsDir': return stubProdsDir;
            default: return $className;
        }
    }

    protected function stubGetUserInfo() {
        // set up mock parameters
        $retval = array();
        $retval['id'] = "1";
        $retval['name'] = $this->name;
        $retval['type'] = $this->type;
        $retval['zone'] = $this->zone;
        $retval['dn'] = $this->dn;
        $retval['info'] = $this->info;
        $retval['comment'] = $this->comment;
        $retval['ctime'] = $this->ctime;
        $retval['mtime'] = $this->mtime;

        return $retval;
    }

}

?>
