diff --git a/sources/Service/Router/Router.php b/sources/Service/Router/Router.php index 1566a4c90..8ef5d015f 100644 --- a/sources/Service/Router/Router.php +++ b/sources/Service/Router/Router.php @@ -138,12 +138,15 @@ class Router { $aRoutes = []; $bUseCache = false === utils::IsDevelopmentEnvironment(); + $bMustWriteCache = false; $sCacheFilePath = $this->GetCacheFileAbsPath(); // Try to read from cache if ($bUseCache) { if (is_file($sCacheFilePath)) { $aRoutes = include $sCacheFilePath; + } else { + $bMustWriteCache = true; } } @@ -180,11 +183,11 @@ class Router } } - // Save to cache - if ($bUseCache) { + // Save to cache if it doesn't exist already + if ($bMustWriteCache) { $sCacheContent = "RequireOnceItopFile('setup/setuputils.class.inc.php'); + } + /** * @covers \Combodo\iTop\Service\Router\Router::GenerateUrl * @dataProvider GenerateUrlProvider @@ -169,6 +179,56 @@ class RouterTest extends ItopTestCase $this->assertEquals($bShouldBePresent, $bIsPresent, "Route '$sRoute' was not expected amongst the available routes."); } + /** + * @covers \Combodo\iTop\Service\Router\Router::GetRoutes + * @return void + * + * @details Covers the cache generation within the GetRoutes method + * @since N°6618 + */ + public function testGetRoutesCacheGeneration(): void + { + $oRouter = Router::GetInstance(); + $sRoutesCacheFilePath = $this->InvokeNonPublicMethod(Router::class, 'GetCacheFileAbsPath', $oRouter, []); + + // Developer mode must be disabled for the routes cache to be used + $oConf = utils::GetConfig(); + $mDeveloperModePreviousValue = $oConf->Get('developer_mode.enabled'); + $oConf->Set('developer_mode.enabled', false); + + // Generate cache for first time + $this->InvokeNonPublicMethod(Router::class, 'GetRoutes', $oRouter, []); + + // Check that file exists and retrieve modification timestamp + if (false === is_file($sRoutesCacheFilePath)) { + $this->fail("Cache file was not generated ($sRoutesCacheFilePath)"); + } + + clearstatcache(); + $iFirstModificationTimestamp = filemtime($sRoutesCacheFilePath); + $this->debug("Initial timestamp: $iFirstModificationTimestamp"); + + // Wait for just 1s to ensure timestamps would be different is the file is re-generated + sleep(1); + + // Call GetRoutes() again to see if cache gets re-generated or not + $this->InvokeNonPublicMethod(Router::class, 'GetRoutes', $oRouter, []); + + // Check that file still exists and that modification timestamp has not changed + if (false === is_file($sRoutesCacheFilePath)) { + $this->fail("Cache file is no longer present, that should not happen! ($sRoutesCacheFilePath)"); + } + + clearstatcache(); + $iSecondModificationTimestamp = filemtime($sRoutesCacheFilePath); + $this->debug("Second timestamp: $iSecondModificationTimestamp"); + + $this->assertSame($iFirstModificationTimestamp, $iSecondModificationTimestamp, "Cache file timestamp changed, seems like cache is not working and was re-generated when it should not!"); + + // Restore previous value for following tests + $oConf->Set('developer_mode.enabled', $mDeveloperModePreviousValue); + } + public function GetRoutesProvider(): array { return [