<?php

/*
 * This file is part of the Stash package.
 *
 * (c) Robert Hafner <tedivm@tedivm.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Stash\Test;

use Stash\Session;
use Stash\Pool;

/**
 * @package Stash
 * @author  Robert Hafner <tedivm@tedivm.com>
 */
class SessionTest extends \PHPUnit\Framework\TestCase
{
    protected $testClass = '\Stash\Session';
    protected $poolClass = '\Stash\Pool';

    protected function setUp()
    {
        if (defined('HHVM_VERSION') && version_compare(HHVM_VERSION, '3.0.0', '<')) {
            $this->markTestSkipped('Sessions not supported on older versions of HHVM.');
        }
    }

    public function testRegisterHandler()
    {
    }

    public function testReadAndWrite()
    {
        $session = $this->getSession();

        $this->assertSame(
            '',
            $session->read('session_id'),
                          'Empty session returns empty string.'
        );

        $this->assertTrue(
            $session->write('session_id', 'session_data'),
                          'Data was written to the session.'
        );
        $this->assertSame(
            'session_data',
            $session->read('session_id'),
                          'Active session returns session data.'
        );
    }

    public function testOpen()
    {
        $pool = $this->getPool();

        $sessionA = $this->getSession($pool);
        $sessionA->open('first', 'session');
        $sessionA->write('shared_id', "session_a_data");

        $sessionB = $this->getSession($pool);
        $sessionB->open('second', 'session');
        $sessionB->write('shared_id', "session_b_data");

        $DataA = $sessionA->read('shared_id');
        $DataB = $sessionB->read('shared_id');

        $this->assertTrue(
            $DataA != $DataB,
                          'Sessions with different paths do not share data.'
        );

        $pool = $this->getPool();

        $sessionA = $this->getSession($pool);
        $sessionA->open('shared_path', 'sessionA');
        $sessionA->write('shared_id', "session_a_data");

        $sessionB = $this->getSession($pool);
        $sessionB->open('shared_path', 'sessionB');
        $sessionB->write('shared_id', "session_b_data");

        $DataA = $sessionA->read('shared_id');
        $DataB = $sessionB->read('shared_id');

        $this->assertTrue(
            $DataA != $DataB,
                          'Sessions with different names do not share data.'
        );
    }

    public function testClose()
    {
        $session = $this->getSession();
        $this->assertTrue(
            $session->close(),
                          'Session was closed'
        );
    }

    public function testDestroy()
    {
        $session = $this->getSession();

        $session->write('session_id', 'session_data');
        $session->write('session_id', 'session_data');
        $this->assertSame(
            'session_data',
            $session->read('session_id'),
                          'Active session returns session data.'
        );

        $this->assertTrue(
            $session->destroy('session_id'),
                          'Data was removed from the session.'
        );

        $this->assertSame(
            '',
            $session->read('session_id'),
                          'Destroyed session returns empty string.'
        );
    }

    public function testGarbageCollect()
    {
        $pool = $this->getPool();

        $sessionA = $this->getSession($pool);
        $sessionA->setOptions(array('ttl' => -30));
        $sessionA->write('session_id', "session_a_data");

        $sessionB = $this->getSession($pool);
        $sessionB->gc(null);

        $sessionC = $this->getSession($pool);
        $this->assertSame(
            '',
            $sessionC->read('session_id'),
                          'Purged session returns empty string.'
        );
    }

    protected function getSession($pool = null)
    {
        if (!isset($pool)) {
            $pool = $this->getPool();
        }

        return new $this->testClass($pool);
    }

    protected function getPool()
    {
        return new $this->poolClass();
    }
}
