Skip to content

Commit

Permalink
test(unit): Cover new methods
Browse files Browse the repository at this point in the history
  • Loading branch information
julienloizelet committed Dec 25, 2024
1 parent 07ab9bf commit 633701d
Show file tree
Hide file tree
Showing 5 changed files with 186 additions and 9 deletions.
1 change: 1 addition & 0 deletions src/Configuration/Capi.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class Capi extends AbstractRemediation
'fallback_remediation',
'ordered_remediations',
'stream_mode',
'bouncing_level',
'clean_ip_cache_duration',
'bad_ip_cache_duration',
'geolocation',
Expand Down
1 change: 1 addition & 0 deletions src/Configuration/Lapi.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class Lapi extends AbstractRemediation
'fallback_remediation',
'ordered_remediations',
'stream_mode',
'bouncing_level',
'clean_ip_cache_duration',
'bad_ip_cache_duration',
'geolocation',
Expand Down
4 changes: 2 additions & 2 deletions tests/Unit/AppSecLapiRemediationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,11 @@
* @uses \CrowdSec\RemediationEngine\CacheStorage\Memcached::getItem
* @uses \CrowdSec\RemediationEngine\Configuration\AbstractCache::addCommonNodes
*
* @covers \CrowdSec\RemediationEngine\AbstractRemediation::handleRemediationFromDecisions
* @covers \CrowdSec\RemediationEngine\AbstractRemediation::getOriginsCount
*
* @uses \CrowdSec\RemediationEngine\AbstractRemediation::sortDecisionsByPriority
* @uses \CrowdSec\RemediationEngine\AbstractRemediation::capRemediationLevel
* @uses \CrowdSec\RemediationEngine\AbstractRemediation::getOriginsCountItem
*
* @covers \CrowdSec\RemediationEngine\AbstractRemediation::incrementRemediationOriginCount
* @covers \CrowdSec\RemediationEngine\AbstractRemediation::getCacheStorage
Expand All @@ -82,7 +83,6 @@
* @covers \CrowdSec\RemediationEngine\AbstractRemediation::getConfig
* @covers \CrowdSec\RemediationEngine\LapiRemediation::getIpRemediation
* @covers \CrowdSec\RemediationEngine\LapiRemediation::storeDecisions
* @covers \CrowdSec\RemediationEngine\LapiRemediation::sortDecisionsByRemediationPriority
* @covers \CrowdSec\RemediationEngine\LapiRemediation::refreshDecisions
* @covers \CrowdSec\RemediationEngine\LapiRemediation::getStreamDecisions
* @covers \CrowdSec\RemediationEngine\Configuration\Capi::getConfigTreeBuilder
Expand Down
40 changes: 36 additions & 4 deletions tests/Unit/CapiRemediationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,6 @@
* @uses \CrowdSec\RemediationEngine\AbstractRemediation::getCountryForIp
* @uses \CrowdSec\RemediationEngine\Configuration\AbstractCache::addCommonNodes
*
* @covers \CrowdSec\RemediationEngine\AbstractRemediation::handleRemediationFromDecisions
* @covers \CrowdSec\RemediationEngine\AbstractRemediation::sortDecisionsByPriority
*
* @uses \CrowdSec\RemediationEngine\AbstractRemediation::incrementRemediationOriginCount
*
* @covers \CrowdSec\RemediationEngine\AbstractRemediation::getCacheStorage
Expand Down Expand Up @@ -85,7 +82,6 @@
* @covers \CrowdSec\RemediationEngine\AbstractRemediation::getConfig
* @covers \CrowdSec\RemediationEngine\CapiRemediation::getIpRemediation
* @covers \CrowdSec\RemediationEngine\CapiRemediation::storeDecisions
* @covers \CrowdSec\RemediationEngine\CapiRemediation::sortDecisionsByPriority
* @covers \CrowdSec\RemediationEngine\CapiRemediation::refreshDecisions
* @covers \CrowdSec\RemediationEngine\Configuration\Capi::getConfigTreeBuilder
* @covers \CrowdSec\RemediationEngine\AbstractRemediation::removeDecisions
Expand Down Expand Up @@ -126,6 +122,11 @@
* @covers \CrowdSec\RemediationEngine\CapiRemediation::handleListResponse
* @covers \CrowdSec\RemediationEngine\AbstractRemediation::processCachedDecisions
* @covers \CrowdSec\RemediationEngine\AbstractRemediation::retrieveRemediationFromCachedDecisions
* @covers \CrowdSec\RemediationEngine\AbstractRemediation::sortDecisionsByPriority
* @covers \CrowdSec\RemediationEngine\AbstractRemediation::capRemediationLevel
* @uses \CrowdSec\RemediationEngine\AbstractRemediation::getOriginsCountItem
*
*
*/
final class CapiRemediationTest extends AbstractRemediation
{
Expand Down Expand Up @@ -1049,6 +1050,37 @@ public function testPrivateOrProtectedMethods()
['If-Modified-Since' => 'Fri, 03 Mar 2023 00:00:00 GMT'],
$result
);

// capRemediationLevel
$result = PHPUnitUtil::callMethod(
$remediation,
'capRemediationLevel',
['ban']
);
$this->assertEquals('ban', $result, 'Remediation should be capped as ban');

$remediationConfigs = ['bouncing_level' => Constants::BOUNCING_LEVEL_DISABLED];
$remediation = new CapiRemediation($remediationConfigs, $this->watcher, $this->cacheStorage, $this->logger);

$result = PHPUnitUtil::callMethod(
$remediation,
'capRemediationLevel',
['ban']
);
$this->assertEquals('bypass', $result, 'Remediation should be capped as bypass');
// We need to add the captcha in ordered_remediations to test the cap
$remediationConfigs = [
'bouncing_level' => Constants::BOUNCING_LEVEL_FLEX,
'ordered_remediations' => ['ban', 'captcha', 'bypass'],
];
$remediation = new CapiRemediation($remediationConfigs, $this->watcher, $this->cacheStorage, $this->logger);

$result = PHPUnitUtil::callMethod(
$remediation,
'capRemediationLevel',
['ban']
);
$this->assertEquals('captcha', $result, 'Remediation should be capped as captcha');
}

/**
Expand Down
149 changes: 146 additions & 3 deletions tests/Unit/LapiRemediationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,14 @@
* @uses \CrowdSec\RemediationEngine\CacheStorage\Memcached::getItem
* @uses \CrowdSec\RemediationEngine\Configuration\AbstractCache::addCommonNodes
*
* @covers \CrowdSec\RemediationEngine\AbstractRemediation::handleRemediationFromDecisions
* @covers \CrowdSec\RemediationEngine\AbstractRemediation::getOriginsCount
* @covers \CrowdSec\RemediationEngine\AbstractRemediation::resetRemediationOriginCount
*
* @uses \CrowdSec\RemediationEngine\AbstractRemediation::sortDecisionsByPriority
* @covers \CrowdSec\RemediationEngine\AbstractRemediation::capRemediationLevel
* @covers \CrowdSec\RemediationEngine\AbstractRemediation::getOriginsCountItem
* @covers \CrowdSec\RemediationEngine\LapiRemediation::getFirstCall
* @covers \CrowdSec\RemediationEngine\LapiRemediation::storeFirstCall
*
* @covers \CrowdSec\RemediationEngine\AbstractRemediation::handleDecisionOrigin
* @covers \CrowdSec\RemediationEngine\AbstractRemediation::incrementRemediationOriginCount
Expand All @@ -85,7 +89,6 @@
* @covers \CrowdSec\RemediationEngine\AbstractRemediation::getConfig
* @covers \CrowdSec\RemediationEngine\LapiRemediation::getIpRemediation
* @covers \CrowdSec\RemediationEngine\LapiRemediation::storeDecisions
* @covers \CrowdSec\RemediationEngine\LapiRemediation::sortDecisionsByRemediationPriority
* @covers \CrowdSec\RemediationEngine\LapiRemediation::refreshDecisions
* @covers \CrowdSec\RemediationEngine\LapiRemediation::getStreamDecisions
* @covers \CrowdSec\RemediationEngine\Configuration\Capi::getConfigTreeBuilder
Expand Down Expand Up @@ -573,14 +576,17 @@ public function testGetIpRemediationInLiveMode($cacheType)
$item->isHit(),
'Config item should be cached'
);
$configItem = $item->get();
$this->assertEqualsWithDelta(
[
AbstractCache::FIRST_LAPI_CALL => time(),
],
$item->get(),
$configItem,
1000, // 1 second delta to avoid false negative
'Config cache item should be as expected'
);
$originalFirstCall = $configItem[AbstractCache::FIRST_LAPI_CALL];
sleep(1); // To test that first LAPI call is cached and do not change
// Test 2 (cached decisions)
$result = $remediation->getIpRemediation(TestConstants::IP_V4);
$this->assertEquals(
Expand All @@ -594,6 +600,20 @@ public function testGetIpRemediationInLiveMode($cacheType)
$originsCount,
'Clean count should be 2'
);
// Additional tests
$item = $adapter->getItem(base64_encode(AbstractCache::CONFIG));
$this->assertEquals(
true,
$item->isHit(),
'First LAPI call should be cached'
);
$finalConfigItem = $item->get();
$finalFirstCall = $finalConfigItem[AbstractCache::FIRST_LAPI_CALL];
$this->assertEquals(
$originalFirstCall,
$finalFirstCall,
'First LAPI call should be the same as at beginning'
);
// Test 3 (no cached decision and 2 actives IP decisions)
$this->cacheStorage->clear();
$originsCount = $remediation->getOriginsCount();
Expand Down Expand Up @@ -675,8 +695,102 @@ public function testGetIpRemediationInLiveMode($cacheType)
$originsCount,
'Origin count should be updated'
);

}

/**
* @dataProvider cacheTypeProvider
*/
public function testResetRemediationOriginCount($cacheType)
{
$this->setCache($cacheType);

$remediationConfigs = ['stream_mode' => false];
// Prepare next tests
$currentTime = time();
$expectedCleanTime = $currentTime + Constants::CACHE_EXPIRATION_FOR_CLEAN_IP;
$this->cacheStorage->method('retrieveDecisionsForIp')->will(
$this->onConsecutiveCalls(
[AbstractCache::STORED => []], // Test 1 : retrieve empty IP decisions
[AbstractCache::STORED => []], // Test 1 : retrieve empty range decisions
[AbstractCache::STORED => [[
'bypass',
$expectedCleanTime,
'clean-bypass-ip-1.2.3.4',
'clean',
]]], // Test 2 : retrieve cached bypass
[AbstractCache::STORED => []] // Test 2 : retrieve empty range
)
);
$this->bouncer->method('getFilteredDecisions')->will(
$this->onConsecutiveCalls(
[], // Test 1 : retrieve empty IP decisions
[
[
'scope' => 'ip',
'value' => TestConstants::IP_V4,
'type' => 'captcha',
'origin' => 'lapi',
'duration' => '1h',
],
[
'scope' => 'ip',
'value' => TestConstants::IP_V4,
'type' => 'ban',
'origin' => 'lapi',
'duration' => '1h',
],
],
)
);

$remediation = new LapiRemediation($remediationConfigs, $this->bouncer, $this->cacheStorage, null);
$result = $remediation->resetRemediationOriginCount('clean', 'bypass');
$this->assertEquals(
false,
$result,
'Should not reset origin count as not existing'
);

// Call 1 (No cached items and no active decision)
$originsCount = $remediation->getOriginsCount();
$this->assertEquals(
[],
$originsCount,
'Origins count should be empty'
);
$remediation->getIpRemediation(TestConstants::IP_V4);
$originsCount = $remediation->getOriginsCount();
$this->assertEquals(
['clean' => ['bypass' => 1]],
$originsCount,
'Origin count should be cached'
);
// Call 2 (cached decisions)
$remediation->getIpRemediation(TestConstants::IP_V4);
$originsCount = $remediation->getOriginsCount();
$this->assertEquals(
['clean' => ['bypass' => 2]],
$originsCount,
'Clean count should be 2'
);
// Test resetting
$result = $remediation->resetRemediationOriginCount('clean', 'bypass');
$this->assertEquals(
true,
$result,
'Should reset origin count'
);

$originsCount = $remediation->getOriginsCount();
$this->assertEquals(
['clean' => ['bypass' => 0]],
$originsCount,
'Clean count should be reset to 0'
);
}


/**
* @dataProvider cacheTypeProvider
*/
Expand Down Expand Up @@ -1416,6 +1530,35 @@ public function testPrivateOrProtectedMethods()
$decision->getOrigin(),
'Should have created a correct decision origin'
);
// capRemediationLevel
$result = PHPUnitUtil::callMethod(
$remediation,
'capRemediationLevel',
['ban']
);
$this->assertEquals('ban', $result, 'Remediation should be capped as ban');

$remediationConfigs = ['bouncing_level' => Constants::BOUNCING_LEVEL_DISABLED];
$remediation = new LapiRemediation($remediationConfigs, $this->bouncer, $this->cacheStorage, $this->logger);

$result = PHPUnitUtil::callMethod(
$remediation,
'capRemediationLevel',
['ban']
);
$this->assertEquals('bypass', $result, 'Remediation should be capped as bypass');

$remediationConfigs = ['bouncing_level' =>
Constants::BOUNCING_LEVEL_FLEX];
$remediation = new LapiRemediation($remediationConfigs, $this->bouncer, $this->cacheStorage, $this->logger);

$result = PHPUnitUtil::callMethod(
$remediation,
'capRemediationLevel',
['ban']
);
$this->assertEquals('captcha', $result, 'Remediation should be capped as captcha');

}

protected function tearDown(): void
Expand Down

0 comments on commit 633701d

Please sign in to comment.