tao-test/app/taoDelivery/test/unit/model/Capacity/InfrastructureCapacityServiceTest.php

183 lines
7.1 KiB
PHP

<?php
/**
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; under version 2
* of the License (non-upgradable).
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Copyright (c) 2019 (original work) Open Assessment Technologies SA ;
*/
namespace oat\taoDelivery\test\unit\model\Capacity;
use common_persistence_KeyValuePersistence;
use oat\generis\persistence\PersistenceManager;
use oat\generis\test\TestCase;
use oat\oatbox\event\EventManager;
use oat\oatbox\log\LoggerService;
use oat\oatbox\mutex\LockService;
use oat\tao\model\metrics\MetricsService;
use oat\taoDelivery\model\Capacity\InfrastructureCapacityService;
use oat\taoDelivery\model\Metrics\AwsLoadMetric;
use Psr\Log\LoggerInterface;
use Symfony\Component\Lock\Factory;
use Symfony\Component\Lock\LockInterface;
class InfrastructureCapacityServiceTest extends TestCase
{
/**
* @dataProvider provideConfigAndMetricDataForCheckCapacity
*/
public function testGetCapacity_WhenConfigOptionsAndMetricDataIsProvided_ThenExpectedValuesAreReturned(
$infrastructureLimit,
$taoLimit,
$cachedCapacity,
$currentInfrastructureLoad,
$expectedCapacity
) {
$service = $this->createInfrastructureCapacityService($infrastructureLimit, $taoLimit, $cachedCapacity, $currentInfrastructureLoad);
$this->assertEquals($expectedCapacity, $service->getCapacity());
}
public function testConsume_WhenCachedServerCapacityIsInsufficient_ThenFalseIsReturned()
{
$service = $this->createInfrastructureCapacityService(50, 100, 0, 50);
$this->assertFalse($service->consume());
}
public function testConsume_WhenCachedServerCapacityIsSufficient_ThenTrueReturnedAndCapacityDecremented()
{
$service = $this->createInfrastructureCapacityService(50, 100, 1, 50, true);
$this->assertTrue($service->consume());
}
/**
* returns array with following structure:
* <code>
* array(
* array(
* (int) infrastructureLimit,
* (int) taoLimit,
* (int) cachedCapacity,
* (int) currentInfrastructureLoad,
* (int) expectedCapacity
* )
* )
* </code>
*
* @return array[]
*/
public function provideConfigAndMetricDataForCheckCapacity()
{
return [
// when there is no cached capacity, and server load is lower than configured threshold,
// then calculated capacity is proportional amount from configured TAO limit
[80, 3000, null, 40, 1500], // no cached capacity, server load limit 80%, current load 40%
[90, 3000, null, 30, 2000], // no cached capacity, server load limit 90%, current load 30%
// when there is no cached capacity, and server load is larger than configured threshold,
// then calculated capacity is negative and a zero capacity is returned
[80, 3000, null, 80, 0],
[80, 3000, null, 81, 0],
[80, 3000, null, 100, 0],
// when there is a cached calculated server capacity, then it is returned
[80, 3000, 5, 100, 5],
[80, 3000, 50, 100, 50],
];
}
/**
* @param $infrastructureLimit
* @param $taoLimit
* @param $cachedCapacity
* @param $currentInfrastructureLoad
* @param bool $shouldDecrementCapacity
* @return InfrastructureCapacityService
*/
private function createInfrastructureCapacityService(
$infrastructureLimit,
$taoLimit,
$cachedCapacity,
$currentInfrastructureLoad,
$shouldDecrementCapacity = false
) {
$serviceLocatorMock = $this->getServiceLocatorMock([
LockService::SERVICE_ID => $this->createLockServiceMock(),
PersistenceManager::SERVICE_ID => $this->createPersistenceManagerMock($cachedCapacity, $shouldDecrementCapacity),
EventManager::SERVICE_ID => $this->createMock(EventManager::class),
LoggerService::SERVICE_ID => $this->createMock(LoggerInterface::class),
MetricsService::class => $this->createMetricsMock($currentInfrastructureLoad),
]);
$service = new InfrastructureCapacityService([
InfrastructureCapacityService::OPTION_INFRASTRUCTURE_LOAD_LIMIT => $infrastructureLimit,
InfrastructureCapacityService::OPTION_TAO_CAPACITY_LIMIT => $taoLimit,
InfrastructureCapacityService::OPTION_TTL => 60,
InfrastructureCapacityService::OPTION_PERSISTENCE => 'testPersistence',
]);
$service->setServiceLocator($serviceLocatorMock);
return $service;
}
/**
* @param $currentInfrastructureLoad
* @return \oat\generis\test\MockObject
*/
private function createMetricsMock($currentInfrastructureLoad)
{
$awsLoadMetricMock = $this->createMock(AwsLoadMetric::class);
$awsLoadMetricMock->method('collect')->willReturn($currentInfrastructureLoad);
$metricsServiceMock = $this->createMock(MetricsService::class);
$metricsServiceMock->method('getOneMetric')->willReturn($awsLoadMetricMock);
return $metricsServiceMock;
}
/**
* @param $cachedCapacity
* @return \oat\generis\test\MockObject
*/
private function createPersistenceManagerMock($cachedCapacity, $shouldDecrementCapacity)
{
$persistenceManagerMock = $this->createMock(PersistenceManager::class);
$persistenceMock = $this->createMock(common_persistence_KeyValuePersistence::class);
$persistenceMock->method('get')->willReturnCallback(function ($argument) use ($cachedCapacity) {
switch ($argument) {
case InfrastructureCapacityService::CAPACITY_TO_PROVIDE_CACHE_KEY:
case InfrastructureCapacityService::CAPACITY_TO_CONSUME_CACHE_KEY:
return $cachedCapacity;
}
});
if ($shouldDecrementCapacity) {
$persistenceMock->expects($this->once())->method('decr')->willReturn(true);
}
$persistenceManagerMock->method('getPersistenceById')->willReturn($persistenceMock);
return $persistenceManagerMock;
}
/**
* @return \oat\generis\test\MockObject
*/
private function createLockServiceMock()
{
$lockServiceMock = $this->createMock(LockService::class);
$lockFactoryMock = $this->createMock(Factory::class);
$lockServiceMock->method('getLockFactory')->willReturn($lockFactoryMock);
$lockMock = $this->createMock(LockInterface::class);
$lockFactoryMock->method('createLock')->willReturn($lockMock);
return $lockServiceMock;
}
}