-
-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #71 from kitsunet/task/add-framework-testing-boile…
…rplate TASK: Benchmark basics
- Loading branch information
Showing
4 changed files
with
217 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
<?php | ||
|
||
/* | ||
* (c) Contributors of the Neos Project - www.neos.io | ||
* Please see the LICENSE file which was distributed with this source code. | ||
*/ | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Neos\BuildEssentials\PhpBench; | ||
|
||
use Neos\BuildEssentials\TestableFramework; | ||
use Neos\Flow\Core\Bootstrap; | ||
use Neos\Flow\Testing\RequestHandler\RuntimeSequenceInvokingRequestHandler; | ||
|
||
/** | ||
* Tools for https://github.com/phpbench/phpbench | ||
*/ | ||
class FrameworkEnabledBenchmark | ||
{ | ||
protected Bootstrap $flowBootstrap; | ||
|
||
/** | ||
* Use with phpbench BeforeClassMethods annotation to prepare persistence schema | ||
*/ | ||
public static function enablePersistence(): void | ||
{ | ||
$_SERVER['FLOW_ROOTPATH'] = TestableFramework::calculateRootPath(); | ||
$bootstrap = TestableFramework::buildBootstrapWithPreselectedRequestHandler(TestableFramework::getApplicationContext(), RuntimeSequenceInvokingRequestHandler::class); | ||
$bootstrap->run(); | ||
TestableFramework::enablePersistence($bootstrap); | ||
} | ||
|
||
/** | ||
* Use with phpbench AfterClassMethods annotation to cleanup persistence schema | ||
*/ | ||
public static function cleanUpPersistence(): void | ||
{ | ||
$_SERVER['FLOW_ROOTPATH'] = TestableFramework::calculateRootPath(); | ||
$bootstrap = TestableFramework::buildBootstrapWithPreselectedRequestHandler(TestableFramework::getApplicationContext(), RuntimeSequenceInvokingRequestHandler::class); | ||
$bootstrap->run(); | ||
TestableFramework::cleanUpPersistence($bootstrap); | ||
} | ||
|
||
/** | ||
* Makes $this->flowBootstrap available with a running request handler that will have booted up the framework in runtime. | ||
* This can be used for any test that requires Flow framework features like the ObjectManager, so that | ||
* the whole booting process will be done before the benchmark measurement. | ||
* Use with phpbench BeforeMethods annotation | ||
* | ||
*/ | ||
public function bootstrapWithTestRequestHandler(): void | ||
{ | ||
$this->withRootPath(); | ||
$this->flowBootstrap = TestableFramework::buildBootstrapWithPreselectedRequestHandler(TestableFramework::getApplicationContext(), RuntimeSequenceInvokingRequestHandler::class); | ||
$this->flowBootstrap->run(); | ||
} | ||
|
||
/** | ||
* Writes the FLOW_ROOTPATH global server variable, so it is available globally when starting the framework | ||
* Use with phpbench BeforeMethods annotation | ||
*/ | ||
public function withRootPath(): void | ||
{ | ||
$_SERVER['FLOW_ROOTPATH'] = TestableFramework::calculateRootPath(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
<?php | ||
|
||
/* | ||
* (c) Contributors of the Neos Project - www.neos.io | ||
* Please see the LICENSE file which was distributed with this source code. | ||
*/ | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Neos\BuildEssentials; | ||
|
||
use Neos\Flow\Annotations as Flow; | ||
use Neos\Flow\Configuration\ConfigurationManager; | ||
use Neos\Flow\Core\Bootstrap; | ||
use Neos\Flow\Core\RequestHandlerInterface; | ||
use Neos\Flow\Persistence\PersistenceManagerInterface; | ||
use Neos\Utility\Files; | ||
|
||
/** | ||
* Low level operations for use in testing, all to be used in static calls. | ||
* | ||
* @Flow\Proxy(false) | ||
*/ | ||
abstract readonly class TestableFramework | ||
{ | ||
/** | ||
* Calculates a FLOW_ROOTPATH | ||
* @return string | ||
*/ | ||
public static function calculateRootPath(): string | ||
{ | ||
$flowRootPathFromEnvironment = trim(getenv('FLOW_ROOTPATH') ?: '', '"\' '); | ||
return $flowRootPathFromEnvironment ?: dirname(__DIR__, 3) . '/'; | ||
} | ||
|
||
public static function getApplicationContext(): string | ||
{ | ||
$flowContextFromEnvironment = trim(getenv('FLOW_CONTEXT') ?: '', '"\' '); | ||
return $flowContextFromEnvironment ?: 'Testing'; | ||
} | ||
|
||
/** | ||
* Build a Flow Bootstrap with an instance of the given class implementing RequestHandlerInterface | ||
* | ||
* @param string $context | ||
* @param class-string<RequestHandlerInterface> $requestHandlerClassname | ||
* @return Bootstrap | ||
*/ | ||
public static function buildBootstrapWithPreselectedRequestHandler(string $context, string $requestHandlerClassname): Bootstrap | ||
{ | ||
$flowBootstrap = new Bootstrap($context); | ||
$requestHandlerInstance = new $requestHandlerClassname($flowBootstrap); | ||
assert($requestHandlerInstance instanceof RequestHandlerInterface); | ||
|
||
$flowBootstrap->registerRequestHandler($requestHandlerInstance); | ||
$flowBootstrap->setPreselectedRequestHandlerClassName($requestHandlerClassname); | ||
return $flowBootstrap; | ||
} | ||
|
||
/** | ||
* Creates an empty table structure according to the active ORM schemas | ||
* | ||
* @param Bootstrap $bootstrap | ||
* @return void | ||
* @throws \Doctrine\ORM\Tools\ToolsException | ||
* @throws \Neos\Flow\Exception | ||
*/ | ||
public static function enablePersistence(Bootstrap $bootstrap): void | ||
{ | ||
$persistenceMangager = $bootstrap->getObjectManager()->get(PersistenceManagerInterface::class); | ||
if (is_callable([$persistenceMangager, 'compile'])) { | ||
$result = $persistenceMangager->compile(); | ||
if ($result === false) { | ||
exit('Could not setup persistence for benchmark'); | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Drops persistence tables after a test | ||
* | ||
* @param Bootstrap $bootstrap | ||
* @return void | ||
* @throws \Neos\Flow\Exception | ||
*/ | ||
public static function cleanUpPersistence(Bootstrap $bootstrap): void | ||
{ | ||
$persistenceManager = $bootstrap->getObjectManager()->get(PersistenceManagerInterface::class); | ||
// Explicitly call persistAll() so that the "allObjectsPersisted" signal is sent even if persistAll() | ||
// has not been called during a test. This makes sure that for example certain repositories can clear | ||
// their internal registry in order to avoid side effects in the following test run. | ||
// Wrap in try/catch to suppress errors after the actual test is run (e.g. validation) | ||
try { | ||
$persistenceManager->persistAll(); | ||
} catch (\Exception $exception) { | ||
} | ||
|
||
if (is_callable([$persistenceManager, 'tearDown'])) { | ||
$persistenceManager->tearDown(); | ||
} | ||
} | ||
|
||
/** | ||
* Cleans up the directory for storing persistent resources during testing | ||
* | ||
* @return void | ||
* @throws \Exception | ||
*/ | ||
public static function cleanupPersistentResourcesDirectory(Bootstrap $bootstrap): void | ||
{ | ||
$settings = $bootstrap->getObjectManager()->get(ConfigurationManager::class)->getConfiguration(ConfigurationManager::CONFIGURATION_TYPE_SETTINGS); | ||
foreach ($settings['Neos']['Flow']['resource']['storages'] as $storageName => $storageSettings) { | ||
if (!isset($storageSettings['storageOptions']['path'])) { | ||
continue; | ||
} | ||
|
||
$resourcesStoragePath = $storageSettings['storageOptions']['path']; | ||
if (!str_contains($resourcesStoragePath, FLOW_PATH_DATA)) { | ||
throw new \Exception(sprintf('The storage path for persistent resources for the Testing context is "%s" for the "%s" storage, but it must point to a directory below "%s". Please check the Flow settings for the Testing context.', $resourcesStoragePath, $storageName, FLOW_PATH_DATA), 1382018388); | ||
} | ||
if (!str_contains($resourcesStoragePath, '/Test/')) { | ||
throw new \Exception(sprintf('The storage path for persistent resources for the Testing context is "%s" for the "%s" storage, but it must contain "/Test/". Please check the Flow settings for the Testing context.', $resourcesStoragePath, $storageName), 1382018388); | ||
} | ||
if (file_exists($resourcesStoragePath)) { | ||
Files::removeDirectoryRecursively($resourcesStoragePath); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,30 +1,28 @@ | ||
<?php | ||
namespace Neos\Flow\Build; | ||
|
||
/* | ||
* This file is part of the Neos Flow build system. | ||
* | ||
* (c) Contributors of the Neos Project - www.neos.io | ||
* | ||
* This package is Open Source Software. For the full copyright and license | ||
* information, please view the LICENSE file which was distributed with this | ||
* source code. | ||
* Please see the LICENSE file which was distributed with this source code. | ||
*/ | ||
|
||
$context = isset($_SERVER['FLOW_CONTEXT']) ? $_SERVER['FLOW_CONTEXT'] : 'Testing'; | ||
declare(strict_types=1); | ||
|
||
namespace Neos\Flow\Build; | ||
|
||
use Neos\BuildEssentials\TestableFramework; | ||
use Neos\Flow\Core\Bootstrap; | ||
use Neos\Flow\Testing\RequestHandler\RuntimeSequenceHttpRequestHandler; | ||
|
||
$context = TestableFramework::getApplicationContext(); | ||
|
||
if (preg_match('/^(?:Testing|Testing\/.+)$/', $context) !== 1) { | ||
die(sprintf('The context "%s" is not allowed. Only "Testing" context or one of its subcontexts "Testing/*" is allowed.', $context)); | ||
} | ||
|
||
$_SERVER['FLOW_ROOTPATH'] = dirname(__FILE__) . '/../../../'; | ||
|
||
if (DIRECTORY_SEPARATOR === '/') { | ||
// Fixes an issue with the autoloader, see FLOW-183 | ||
shell_exec('cd ' . escapeshellarg($_SERVER['FLOW_ROOTPATH']) . ' && FLOW_CONTEXT=' . escapeshellarg($context) . ' ./flow neos.flow:cache:warmup'); | ||
} | ||
$_SERVER['FLOW_ROOTPATH'] = TestableFramework::calculateRootPath(); | ||
|
||
require_once($_SERVER['FLOW_ROOTPATH'] . 'Packages/Framework/Neos.Flow/Classes/Core/Bootstrap.php'); | ||
$bootstrap = new \Neos\Flow\Core\Bootstrap($context); | ||
$bootstrap->setPreselectedRequestHandlerClassName(\Neos\Flow\Tests\FunctionalTestRequestHandler::class); | ||
$bootstrap = new Bootstrap($context); | ||
$bootstrap->registerRequestHandler(new RuntimeSequenceHttpRequestHandler($bootstrap)); | ||
$bootstrap->setPreselectedRequestHandlerClassName(RuntimeSequenceHttpRequestHandler::class); | ||
$bootstrap->run(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters