1<?php 2 3/* 4 * This file is part of the Stash package. 5 * 6 * (c) Robert Hafner <tedivm@tedivm.com> 7 * 8 * For the full copyright and license information, please view the LICENSE 9 * file that was distributed with this source code. 10 */ 11 12namespace Stash\Test; 13 14use Stash\Exception\InvalidArgumentException; 15use Stash\Pool; 16use Stash\Driver\Ephemeral; 17use Stash\Test\Stubs\LoggerStub; 18use Stash\Test\Stubs\DriverExceptionStub; 19 20/** 21 * @package Stash 22 * @author Robert Hafner <tedivm@tedivm.com> 23 */ 24class AbstractPoolTest extends \PHPUnit\Framework\TestCase 25{ 26 protected $data = array(array('test', 'test')); 27 protected $multiData = array('key' => 'value', 28 'key1' => 'value1', 29 'key2' => 'value2', 30 'key3' => 'value3'); 31 32 protected $poolClass = '\Stash\Pool'; 33 34 public function testSetDriver() 35 { 36 $driver = new Ephemeral(); 37 $pool = new $this->poolClass($driver); 38 $this->assertAttributeEquals($driver, 'driver', $pool); 39 } 40 41 public function testSetItemDriver() 42 { 43 $pool = $this->getTestPool(); 44 $stash = $pool->getItem('test'); 45 $this->assertAttributeInstanceOf('Stash\Driver\Ephemeral', 'driver', $stash, 'set driver is pushed to new stash objects'); 46 } 47 48 public function testSetItemClass() 49 { 50 $mockItem = $this->createMock('Stash\Interfaces\ItemInterface'); 51 $mockClassName = get_class($mockItem); 52 $pool = $this->getTestPool(); 53 54 $this->assertTrue($pool->setItemClass($mockClassName)); 55 $this->assertAttributeEquals($mockClassName, 'itemClass', $pool); 56 } 57 58 public function testSetItemClassFakeClassException() 59 { 60 try { 61 $pool = $this->getTestPool(); 62 $pool->setItemClass('FakeClassName'); 63 } catch (\Exception $expected) { 64 return; 65 } 66 $this->fail('An expected exception has not been raised.'); 67 } 68 69 public function testSetItemClassImproperClassException() 70 { 71 try { 72 $pool = $this->getTestPool(); 73 $pool->setItemClass('\stdClass'); 74 } catch (\Exception $expected) { 75 return; 76 } 77 $this->fail('An expected exception has not been raised.'); 78 } 79 80 public function testGetItem() 81 { 82 $pool = $this->getTestPool(); 83 84 $stash = $pool->getItem('base/one'); 85 $this->assertInstanceOf('Stash\Item', $stash, 'getItem returns a Stash\Item object'); 86 87 $stash->set($this->data)->save(); 88 $storedData = $stash->get(); 89 $this->assertEquals($this->data, $storedData, 'getItem returns working Stash\Item object'); 90 91 $key = $stash->getKey(); 92 $this->assertEquals('base/one', $key, 'Pool sets proper Item key.'); 93 94 $pool->setNamespace('TestNamespace'); 95 $item = $pool->getItem('test/item'); 96 97 $this->assertAttributeEquals('TestNamespace', 'namespace', $item, 'Pool sets Item namespace.'); 98 } 99 100 public function testSaveItem() 101 { 102 $pool = $this->getTestPool(); 103 104 $this->assertFalse($pool->hasItem('base/one'), 'Pool->hasItem() returns false for item without stored data.'); 105 $item = $pool->getItem('base/one'); 106 $this->assertInstanceOf('Stash\Item', $item, 'getItem returns a Stash\Item object'); 107 108 $key = $item->getKey(); 109 $this->assertEquals('base/one', $key, 'Pool sets proper Item key.'); 110 111 $item->set($this->data); 112 $this->assertTrue($pool->save($item), 'Pool->save() returns true.'); 113 $storedData = $item->get(); 114 $this->assertEquals($this->data, $storedData, 'Pool->save() returns proper data on passed Item.'); 115 116 $item = $pool->getItem('base/one'); 117 $storedData = $item->get(); 118 $this->assertEquals($this->data, $storedData, 'Pool->save() returns proper data on new Item instance.'); 119 120 $this->assertTrue($pool->hasItem('base/one'), 'Pool->hasItem() returns true for item with stored data.'); 121 122 $pool->setNamespace('TestNamespace'); 123 $item = $pool->getItem('test/item'); 124 125 $this->assertAttributeEquals('TestNamespace', 'namespace', $item, 'Pool sets Item namespace.'); 126 } 127 128 129 public function testSaveDeferredItem() 130 { 131 $pool = $this->getTestPool(); 132 133 $this->assertFalse($pool->hasItem('base/one'), 'Pool->hasItem() returns false for item without stored data.'); 134 $item = $pool->getItem('base/one'); 135 $this->assertInstanceOf('Stash\Item', $item, 'getItem returns a Stash\Item object'); 136 137 $key = $item->getKey(); 138 $this->assertEquals('base/one', $key, 'Pool sets proper Item key.'); 139 140 $item->set($this->data); 141 $this->assertTrue($pool->saveDeferred($item), 'Pool->save() returns true.'); 142 $storedData = $item->get(); 143 $this->assertEquals($this->data, $storedData, 'Pool->save() returns proper data on passed Item.'); 144 145 $item = $pool->getItem('base/one'); 146 $storedData = $item->get(); 147 $this->assertEquals($this->data, $storedData, 'Pool->save() returns proper data on new Item instance.'); 148 149 $this->assertTrue($pool->hasItem('base/one'), 'Pool->hasItem() returns true for item with stored data.'); 150 151 $pool->setNamespace('TestNamespace'); 152 $item = $pool->getItem('test/item'); 153 154 $this->assertAttributeEquals('TestNamespace', 'namespace', $item, 'Pool sets Item namespace.'); 155 } 156 157 public function testHasItem() 158 { 159 $pool = $this->getTestPool(); 160 $this->assertFalse($pool->hasItem('base/one'), 'Pool->hasItem() returns false for item without stored data.'); 161 $item = $pool->getItem('base/one'); 162 $item->set($this->data); 163 $pool->save($item); 164 $this->assertTrue($pool->hasItem('base/one'), 'Pool->hasItem() returns true for item with stored data.'); 165 } 166 167 public function testCommit() 168 { 169 $pool = $this->getTestPool(); 170 $this->assertTrue($pool->commit()); 171 } 172 173 174 /** 175 * @expectedException InvalidArgumentException 176 * @expectedExceptionMessage Invalid or Empty Node passed to getItem constructor. 177 */ 178 public function testGetItemInvalidKeyMissingNode() 179 { 180 $pool = $this->getTestPool(); 181 $item = $pool->getItem('This/Test//Fail'); 182 } 183 184 public function testGetItems() 185 { 186 $pool = $this->getTestPool(); 187 188 $keys = array_keys($this->multiData); 189 190 $cacheIterator = $pool->getItems($keys); 191 $keyData = $this->multiData; 192 foreach ($cacheIterator as $key => $stash) { 193 $this->assertTrue($stash->isMiss(), 'new Cache in iterator is empty'); 194 $stash->set($keyData[$key])->save(); 195 unset($keyData[$key]); 196 } 197 $this->assertCount(0, $keyData, 'all keys are accounted for the in cache iterator'); 198 199 $cacheIterator = $pool->getItems($keys); 200 foreach ($cacheIterator as $key => $stash) { 201 $this->assertEquals($key, $stash->getKey(), 'Item key is not equals key in iterator'); 202 $data = $stash->get($key); 203 $this->assertEquals($this->multiData[$key], $data, 'data put into the pool comes back the same through iterators.'); 204 } 205 } 206 207 public function testDeleteItems() 208 { 209 $pool = $this->getTestPool(); 210 211 $keys = array_keys($this->multiData); 212 213 $cacheIterator = $pool->getItems($keys); 214 $keyData = $this->multiData; 215 foreach ($cacheIterator as $stash) { 216 $key = $stash->getKey(); 217 $this->assertTrue($stash->isMiss(), 'new Cache in iterator is empty'); 218 $stash->set($keyData[$key])->save(); 219 unset($keyData[$key]); 220 } 221 $this->assertCount(0, $keyData, 'all keys are accounted for the in cache iterator'); 222 223 $cacheIterator = $pool->getItems($keys); 224 foreach ($cacheIterator as $item) { 225 $key = $item->getKey(); 226 $data = $item->get($key); 227 $this->assertEquals($this->multiData[$key], $data, 'data put into the pool comes back the same through iterators.'); 228 } 229 230 $this->assertTrue($pool->deleteItems($keys), 'deleteItems returns true.'); 231 $cacheIterator = $pool->getItems($keys); 232 foreach ($cacheIterator as $item) { 233 $this->assertTrue($item->isMiss(), 'data cleared using deleteItems is removed from the cache.'); 234 } 235 } 236 237 238 239 public function testClearCache() 240 { 241 $pool = $this->getTestPool(); 242 243 $stash = $pool->getItem('base/one'); 244 $stash->set($this->data)->save(); 245 $this->assertTrue($pool->clear(), 'clear returns true'); 246 247 $stash = $pool->getItem('base/one'); 248 $this->assertNull($stash->get(), 'clear removes item'); 249 $this->assertTrue($stash->isMiss(), 'clear causes cache miss'); 250 } 251 252 public function testPurgeCache() 253 { 254 $pool = $this->getTestPool(); 255 256 $stash = $pool->getItem('base/one'); 257 $stash->set($this->data)->expiresAfter(-600)->save(); 258 $this->assertTrue($pool->purge(), 'purge returns true'); 259 260 $stash = $pool->getItem('base/one'); 261 $this->assertNull($stash->get(), 'purge removes item'); 262 $this->assertTrue($stash->isMiss(), 'purge causes cache miss'); 263 } 264 265 public function testNamespacing() 266 { 267 $pool = $this->getTestPool(); 268 269 $this->assertAttributeEquals(null, 'namespace', $pool, 'Namespace starts empty.'); 270 $this->assertTrue($pool->setNamespace('TestSpace'), 'setNamespace returns true.'); 271 $this->assertAttributeEquals('TestSpace', 'namespace', $pool, 'setNamespace sets the namespace.'); 272 $this->assertEquals('TestSpace', $pool->getNamespace(), 'getNamespace returns current namespace.'); 273 274 $this->assertTrue($pool->setNamespace(), 'setNamespace returns true when setting null.'); 275 $this->assertAttributeEquals(null, 'namespace', $pool, 'setNamespace() empties namespace.'); 276 $this->assertFalse($pool->getNamespace(), 'getNamespace returns false when no namespace is set.'); 277 } 278 279 /** 280 * @expectedException InvalidArgumentException 281 * @expectedExceptionMessage Namespace must be alphanumeric. 282 */ 283 public function testInvalidNamespace() 284 { 285 $pool = $this->getTestPool(); 286 $pool->setNamespace('!@#$%^&*('); 287 } 288 289 290 public function testSetLogger() 291 { 292 $pool = $this->getTestPool(); 293 294 $driver = new DriverExceptionStub(); 295 $pool->setDriver($driver); 296 297 $logger = new LoggerStub(); 298 $pool->setLogger($logger); 299 300 $this->assertAttributeInstanceOf('Stash\Test\Stubs\LoggerStub', 'logger', $pool, 'setLogger injects logger into Pool.'); 301 302 $item = $pool->getItem('testItem'); 303 $this->assertAttributeInstanceOf('Stash\Test\Stubs\LoggerStub', 'logger', $item, 'setLogger injects logger into Pool.'); 304 } 305 306 public function testLoggerClear() 307 { 308 $pool = $this->getTestPool(); 309 310 $driver = new DriverExceptionStub(); 311 $pool->setDriver($driver); 312 313 $logger = new LoggerStub(); 314 $pool->setLogger($logger); 315 316 // triggerlogging 317 $pool->clear(); 318 319 $this->assertInstanceOf( 320 'Stash\Test\Exception\TestException', 321 $logger->lastContext['exception'], 322 'Logger was passed exception in event context.' 323 ); 324 325 $this->assertTrue(strlen($logger->lastMessage) > 0, 'Logger message set after "get" exception.'); 326 $this->assertEquals('critical', $logger->lastLevel, 'Exceptions logged as critical.'); 327 } 328 329 public function testLoggerPurge() 330 { 331 $pool = $this->getTestPool(); 332 333 $driver = new DriverExceptionStub(); 334 $pool->setDriver($driver); 335 336 $logger = new LoggerStub(); 337 $pool->setLogger($logger); 338 339 // triggerlogging 340 $pool->purge(); 341 342 $this->assertInstanceOf( 343 'Stash\Test\Exception\TestException', 344 $logger->lastContext['exception'], 345 'Logger was passed exception in event context.' 346 ); 347 $this->assertTrue(strlen($logger->lastMessage) > 0, 'Logger message set after "set" exception.'); 348 $this->assertEquals('critical', $logger->lastLevel, 'Exceptions logged as critical.'); 349 } 350 351 /** 352 * @return \Stash\Pool 353 */ 354 protected function getTestPool() 355 { 356 return new $this->poolClass(); 357 } 358} 359