<?php

/*
 * @copyright NetMonsters <team@netmonsters.ru>
 * @link http://netmonsters.ru
 * @package Majestic
 * @subpackage UnitTests
 * @since 2011-10-25
 * 
 * Unit tests for MemcacheCache class
 * 
 * Tests need test_helpers extension by Sebastian Bergmann
 */


require_once dirname(__FILE__) . '/../../cache/Cache.php';
require_once dirname(__FILE__) . '/../../cache/MemcacheCache.php';

class MemcacheCacheTest extends PHPUnit_Framework_TestCase
{

    protected function setUp()
    {
        $this->getMock('Memcache');

        set_new_overload(array($this, 'newCallback'));
    }

    public function testConstruct()
    {
        $config = array('key_salt' => 'some', 'host' => array('hostname' => 'localhost', 'port' => 8080));


        $memcache = new MemcacheCache($config);
        $this->assertAttributeInstanceOf('TestCache', 'connection', $memcache);
    }

    /**
     * @expectedException Exception
     * @expectedExceptionMessage Configuration must have a
     * @TODO: MemcacheCache::__construct - empty config array passes with no host params
     */
    public function testWrongConfig()
    {
        $config = array('some' => array());

        $memcache = new MemcacheCache($config);
    }

    public function testAddGet()
    {
        $memcache = new MemcacheCache(array());
        $this->assertTrue($memcache->add('key', 'value'));
        $this->assertEquals('value', $memcache->get('key'));
        $this->assertFalse($memcache->add('key', 'newvalue'));
    }

    public function testIncrementDecrement()
    {
        $memcache = new MemcacheCache(array());

        $memcache->add('one', 1);
        $memcache->add('two', 2);
        $memcache->add('three', 'three');

        $this->assertTrue($memcache->increment('one'));
        $this->assertEquals(2, $memcache->get('one'));
        $this->assertTrue($memcache->decrement('two'));
        $this->assertEquals(1, $memcache->get('two'));

        $this->assertFalse($memcache->decrement('three'));
    }

    public function testDelete()
    {
        $memcache = new MemcacheCache(array());

        $memcache->add('one', 1);
        $memcache->add('two', 2);

        $memcache->del('one');
        $this->assertEquals(2, $memcache->get('two'));
        $this->assertFalse($memcache->get('one'));
    }

    public function testFlush()
    {
        $memcache = new MemcacheCache(array());

        $memcache->add('one', 1);
        $memcache->add('two', 2);
        $memcache->add('three', 'three');

        $this->assertEquals('three', 'three');

        $memcache->flush();

        $this->assertFalse($memcache->get('three'));
        $this->assertFalse($memcache->get('one'));
    }

    public function testSetReplace()
    {
        $memcache = new MemcacheCache(array());

        $memcache->add('one', 1);
        $memcache->add('two', 2);
        $memcache->add('three', 'three');
        $memcache->set('one', 30);
        $memcache->replace('three', 3);

        $this->assertEquals(30, $memcache->get('one'));
        $this->assertEquals(3, $memcache->get('three'));
    }

    protected function newCallback($className)
    {
        switch ($className) {
            case 'Memcache':
                return 'TestCache';
            default:
                return $className;
        }
    }

    public function tearDown()
    {
        unset_new_overload();
    }

}

class TestCache
{

    private $vals = array();

    public function addServer($host, $port)
    {
        return true;
    }

    public function add($key, $value, $some, $expire = 0)
    {
        if(!isset($this->vals[$key])) {
            $this->vals[$key] = $value;
            return true;
        }
        return false;
    }

    public function decrement($key, $decrement = 1)
    {
        if (isset($this->vals[$key]) && is_int($this->vals[$key])) {
            $this->vals[$key]--;
            return true;
        }
        return false;
    }

    public function delete($key)
    {
        if (isset($this->vals[$key])) {
            unset($this->vals[$key]);
        }
        return true;
    }

    public function flush()
    {
        $this->vals = array();
    }

    public function get($key)
    {
        if (isset($this->vals[$key])) {
            return $this->vals[$key];
        }
        return false;
    }

    public function increment($key, $increment = 1)
    {
        if (isset($this->vals[$key]) && is_int($this->vals[$key])) {
            $this->vals[$key]++;
            return true;
        }
        return false;
    }

    public function replace($key, $value, $any = null, $expire = 0)
    {
        if (isset($this->vals[$key])) {
            $this->vals[$key] = $value;
            return true;
        }
        return false;
    }

    public function set($key, $value, $any = null, $expire = 0)
    {
        $this->vals[$key] = $value;
        return true;
    }

}