Files
michaelschiemer/tests/Cache/Warming/PredictiveWarmingStrategyTest.php

124 lines
4.3 KiB
PHP

<?php
declare(strict_types=1);
use App\Framework\Cache\Cache;
use App\Framework\Cache\CacheKey;
use App\Framework\Cache\CacheItem;
use App\Framework\Cache\Driver\InMemoryCache;
use App\Framework\Cache\GeneralCache;
use App\Framework\Serializer\Php\PhpSerializer;
use App\Framework\Cache\Warming\Strategies\PredictiveWarmingStrategy;
use App\Framework\Cache\Warming\ValueObjects\WarmupPriority;
use App\Framework\Core\ValueObjects\Duration;
describe('PredictiveWarmingStrategy', function () {
beforeEach(function () {
// Use real cache instead of mocks
$inMemoryCache = new InMemoryCache();
$serializer = new PhpSerializer();
$this->cache = new GeneralCache($inMemoryCache, $serializer);
});
it('has correct name', function () {
$strategy = new PredictiveWarmingStrategy($this->cache);
expect($strategy->getName())->toBe('predictive');
});
it('has background priority', function () {
$strategy = new PredictiveWarmingStrategy($this->cache);
expect($strategy->getPriority())->toBe(WarmupPriority::BACKGROUND->value);
});
it('should not run without sufficient access patterns', function () {
// No access patterns in cache (cache miss)
$strategy = new PredictiveWarmingStrategy($this->cache);
expect($strategy->shouldRun())->toBeFalse();
});
it('should run with sufficient access patterns', function () {
// Set up access patterns in cache (10+ patterns)
$accessPatterns = [];
for ($i = 0; $i < 15; $i++) {
$accessPatterns["pattern_{$i}"] = [
'access_count' => 10 + $i,
'hourly_distribution' => array_fill(0, 24, 0.04),
'daily_distribution' => array_fill(0, 7, 0.14),
];
}
// Store in cache with the key that PredictiveWarmingStrategy uses
$key = CacheKey::fromString('warmup_access_patterns');
$this->cache->set(CacheItem::forSet($key, $accessPatterns, Duration::fromHours(1)));
$strategy = new PredictiveWarmingStrategy($this->cache);
expect($strategy->shouldRun())->toBeTrue();
});
it('estimates reasonable duration', function () {
$strategy = new PredictiveWarmingStrategy($this->cache);
$duration = $strategy->getEstimatedDuration();
expect($duration)->toBeGreaterThan(0);
expect($duration)->toBeLessThan(300); // Should be < 5 minutes
});
it('warms predicted cache keys', function () {
// Set up access patterns with high probability
$currentHour = (int) date('G');
$currentDay = (int) date('N') - 1;
$accessPatterns = [
'key1' => [
'access_count' => 50,
'hourly_distribution' => array_fill(0, 24, 0.04),
'daily_distribution' => array_fill(0, 7, 0.14),
],
'key2' => [
'access_count' => 30,
'hourly_distribution' => array_fill(0, 24, 0.04),
'daily_distribution' => array_fill(0, 7, 0.14),
],
];
// Boost current hour/day to ensure high probability
$accessPatterns['key1']['hourly_distribution'][$currentHour] = 0.5;
$accessPatterns['key1']['daily_distribution'][$currentDay] = 0.5;
// Store access patterns in cache
$key = CacheKey::fromString('warmup_access_patterns');
$this->cache->set(CacheItem::forSet($key, $accessPatterns));
$strategy = new PredictiveWarmingStrategy($this->cache);
$result = $strategy->warmup();
// Result should complete without errors
expect($result->itemsFailed)->toBe(0);
});
it('skips low probability keys', function () {
$accessPatterns = [
'low_prob_key' => [
'access_count' => 2, // Below MIN_ACCESS_COUNT
'hourly_distribution' => array_fill(0, 24, 0.01),
'daily_distribution' => array_fill(0, 7, 0.01),
],
];
// Store low probability access patterns in cache
$key = CacheKey::fromString('warmup_access_patterns');
$this->cache->set(CacheItem::forSet($key, $accessPatterns));
$strategy = new PredictiveWarmingStrategy($this->cache);
$result = $strategy->warmup();
// No items warmed due to low probability
expect($result->itemsWarmed)->toBe(0);
});
});