- Add comprehensive health check system with multiple endpoints - Add Prometheus metrics endpoint - Add production logging configurations (5 strategies) - Add complete deployment documentation suite: * QUICKSTART.md - 30-minute deployment guide * DEPLOYMENT_CHECKLIST.md - Printable verification checklist * DEPLOYMENT_WORKFLOW.md - Complete deployment lifecycle * PRODUCTION_DEPLOYMENT.md - Comprehensive technical reference * production-logging.md - Logging configuration guide * ANSIBLE_DEPLOYMENT.md - Infrastructure as Code automation * README.md - Navigation hub * DEPLOYMENT_SUMMARY.md - Executive summary - Add deployment scripts and automation - Add DEPLOYMENT_PLAN.md - Concrete plan for immediate deployment - Update README with production-ready features All production infrastructure is now complete and ready for deployment.
140 lines
4.7 KiB
PHP
140 lines
4.7 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Tests\Unit\Framework\Cache;
|
|
|
|
use App\Framework\Cache\CacheItem;
|
|
use App\Framework\Cache\CacheKey;
|
|
use App\Framework\Cache\Driver\InMemoryCache;
|
|
use App\Framework\Cache\GeneralCache;
|
|
use App\Framework\Core\ValueObjects\Duration;
|
|
use App\Framework\Serializer\Php\PhpSerializer;
|
|
|
|
test('cache can store and retrieve values', function () {
|
|
$cache = new GeneralCache(new InMemoryCache(), new PhpSerializer());
|
|
$key = CacheKey::fromString('test-key');
|
|
|
|
$result = $cache->set(CacheItem::forSet($key, 'test-value'));
|
|
expect($result)->toBeTrue();
|
|
|
|
$resultItem = $cache->get($key);
|
|
expect($resultItem->isHit)->toBeTrue();
|
|
expect($resultItem->value)->toBe('test-value');
|
|
});
|
|
|
|
test('cache returns miss for non-existent key', function () {
|
|
$cache = new GeneralCache(new InMemoryCache(), new PhpSerializer());
|
|
$key = CacheKey::fromString('non-existent');
|
|
|
|
$item = $cache->get($key);
|
|
expect($item->isHit)->toBeFalse();
|
|
expect($item->value)->toBeNull();
|
|
});
|
|
|
|
test('cache can check if key exists', function () {
|
|
$cache = new GeneralCache(new InMemoryCache(), new PhpSerializer());
|
|
$key = CacheKey::fromString('test-key');
|
|
|
|
$hasResult = $cache->has($key);
|
|
expect($hasResult[$key->toString()])->toBeFalse();
|
|
|
|
$cache->set(CacheItem::forSet($key, 'value'));
|
|
$hasResult = $cache->has($key);
|
|
expect($hasResult[$key->toString()])->toBeTrue();
|
|
});
|
|
|
|
test('cache can forget keys', function () {
|
|
$cache = new GeneralCache(new InMemoryCache(), new PhpSerializer());
|
|
$key = CacheKey::fromString('test-key');
|
|
|
|
$cache->set(CacheItem::forSet($key, 'value'));
|
|
$hasResult = $cache->has($key);
|
|
expect($hasResult[$key->toString()])->toBeTrue();
|
|
|
|
$result = $cache->forget($key);
|
|
expect($result)->toBeTrue();
|
|
$hasResult = $cache->has($key);
|
|
expect($hasResult[$key->toString()])->toBeFalse();
|
|
});
|
|
|
|
test('cache can clear all entries', function () {
|
|
$cache = new GeneralCache(new InMemoryCache(), new PhpSerializer());
|
|
$key1 = CacheKey::fromString('key1');
|
|
$key2 = CacheKey::fromString('key2');
|
|
|
|
$cache->set(CacheItem::forSet($key1, 'value1'));
|
|
$cache->set(CacheItem::forSet($key2, 'value2'));
|
|
|
|
$result = $cache->clear();
|
|
expect($result)->toBeTrue();
|
|
|
|
$hasResult1 = $cache->has($key1);
|
|
$hasResult2 = $cache->has($key2);
|
|
expect($hasResult1[$key1->toString()])->toBeFalse();
|
|
expect($hasResult2[$key2->toString()])->toBeFalse();
|
|
});
|
|
|
|
test('cache remember pattern works', function () {
|
|
$cache = new GeneralCache(new InMemoryCache(), new PhpSerializer());
|
|
$key = CacheKey::fromString('test-key');
|
|
$callCount = 0;
|
|
|
|
$callback = function () use (&$callCount) {
|
|
$callCount++;
|
|
|
|
return 'computed-value';
|
|
};
|
|
|
|
// First call should execute callback
|
|
$item1 = $cache->remember($key, $callback);
|
|
expect($item1->value)->toBe('computed-value');
|
|
expect($callCount)->toBe(1);
|
|
|
|
// Second call should return cached value
|
|
$item2 = $cache->remember($key, $callback);
|
|
expect($item2->value)->toBe('computed-value');
|
|
expect($callCount)->toBe(1); // Callback not called again
|
|
});
|
|
|
|
test('cache respects TTL', function () {
|
|
$cache = new GeneralCache(new InMemoryCache(), new PhpSerializer());
|
|
$key = CacheKey::fromString('test-key');
|
|
$ttl = Duration::fromSeconds(60);
|
|
|
|
// This test would need a mock or a way to advance time
|
|
// For now, just test that TTL parameter is accepted
|
|
$result = $cache->set(CacheItem::forSet($key, 'value', $ttl));
|
|
expect($result)->toBeTrue();
|
|
});
|
|
|
|
test('cache can store different data types', function () {
|
|
$cache = new GeneralCache(new InMemoryCache(), new PhpSerializer());
|
|
|
|
// String
|
|
$stringKey = CacheKey::fromString('string');
|
|
$cache->set(CacheItem::forSet($stringKey, 'test'));
|
|
expect($cache->get($stringKey)->value)->toBe('test');
|
|
|
|
// Integer
|
|
$intKey = CacheKey::fromString('int');
|
|
$cache->set(CacheItem::forSet($intKey, 42));
|
|
expect($cache->get($intKey)->value)->toBe(42);
|
|
|
|
// Array
|
|
$arrayKey = CacheKey::fromString('array');
|
|
$cache->set(CacheItem::forSet($arrayKey, ['a' => 1, 'b' => 2]));
|
|
expect($cache->get($arrayKey)->value)->toBe(['a' => 1, 'b' => 2]);
|
|
|
|
// Object - stdClass becomes __PHP_Incomplete_Class when deserialized
|
|
// This is expected PHP behavior with PhpSerializer
|
|
$objectKey = CacheKey::fromString('object');
|
|
$obj = (object) ['test' => 'value', 'number' => 42];
|
|
$cache->set(CacheItem::forSet($objectKey, $obj));
|
|
$result = $cache->get($objectKey);
|
|
|
|
// Verify object was cached (becomes __PHP_Incomplete_Class on deserialization)
|
|
expect($result->value)->toBeObject();
|
|
expect($result->value::class)->toBe('__PHP_Incomplete_Class');
|
|
});
|