Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG-5.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ All notable changes are documented here. The format is based on [Keep a Changelo

### Added

- Benchmark subjects for Acl, Cache, Config, Flash, Forms, Jwt, Logger, Security, Session and Validation in `tests/benchmarks`. [#17695](https://github.com/phalcon/cphalcon/issues/17695)

### Fixed

Expand Down
96 changes: 96 additions & 0 deletions tests/benchmarks/Acl/AclBench.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<?php

/**
* This file is part of the Phalcon Framework.
*
* (c) Phalcon Team <team@phalcon.io>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace Phalcon\Tests\Benchmarks\Acl;

use Phalcon\Acl\Adapter\Memory;
use Phalcon\Di\Di;
use PhpBench\Attributes\BeforeMethods;
use PhpBench\Attributes\Revs;
use RuntimeException;

#[BeforeMethods('setUp')]
final class AclBench
{
private const ACCESS = ['index', 'view', 'edit', 'delete'];

private const COMPONENTS = ['posts', 'comments', 'users', 'settings', 'reports'];

private Memory $acl;

public function setUp(): void
{
Di::reset();

$this->acl = $this->buildAcl();
}

/**
* The ACL with 4 roles and 5 components, as one request makes it.
*/
#[Revs(200)]
public function benchBuild(): void
{
$acl = $this->buildAcl();

if (true !== $acl->isAllowed('admin', 'settings', 'delete')) {
throw new RuntimeException('Unexpected value: false');
}
}

public function benchIsAllowed(): void
{
if (true !== $this->acl->isAllowed('editor', 'posts', 'edit')) {
throw new RuntimeException('Unexpected value: false');
}
}

/**
* The access comes from guest, through user (editor inherits user).
*/
public function benchIsAllowedInherited(): void
{
if (true !== $this->acl->isAllowed('editor', 'comments', 'view')) {
throw new RuntimeException('Unexpected value: false');
}
}

public function benchIsDenied(): void
{
if (false !== $this->acl->isAllowed('guest', 'users', 'delete')) {
throw new RuntimeException('Unexpected value: true');
}
}

private function buildAcl(): Memory
{
$acl = new Memory();

$acl->addRole('guest');
$acl->addRole('user', 'guest');
$acl->addRole('editor', 'user');
$acl->addRole('admin', 'editor');

foreach (self::COMPONENTS as $component) {
$acl->addComponent($component, self::ACCESS);
}

$acl->allow('guest', 'posts', ['index', 'view']);
$acl->allow('guest', 'comments', ['index', 'view']);
$acl->allow('user', 'comments', 'edit');
$acl->allow('editor', 'posts', ['edit', 'delete']);
$acl->allow('admin', '*', '*');

return $acl;
}
}
80 changes: 80 additions & 0 deletions tests/benchmarks/Cache/CacheBench.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?php

/**
* This file is part of the Phalcon Framework.
*
* (c) Phalcon Team <team@phalcon.io>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace Phalcon\Tests\Benchmarks\Cache;

use Phalcon\Cache\AdapterFactory;
use Phalcon\Cache\Cache;
use Phalcon\Di\Di;
use Phalcon\Storage\SerializerFactory;
use PhpBench\Attributes\BeforeMethods;
use RuntimeException;

#[BeforeMethods('setUp')]
final class CacheBench
{
private const ROBOTS = ['one', 'two', 'three'];

private Cache $cache;

private int $counter = 0;

public function setUp(): void
{
Di::reset();

$this->cache = $this->newCache();
$this->cache->set('robots', self::ROBOTS);
}

/**
* The two factories, the memory adapter and the cache, as one request
* makes them.
*/
public function benchCreate(): void
{
$cache = $this->newCache();

if (false !== $cache->has('missing')) {
throw new RuntimeException('Unexpected value: true');
}
}

public function benchGet(): void
{
$actual = $this->cache->get('robots');

if (self::ROBOTS !== $actual) {
throw new RuntimeException(sprintf('Unexpected value: %s', var_export($actual, true)));
}
}

/**
* set() of a key that exists, with a new value on each call.
*/
public function benchSet(): void
{
$this->counter++;

if (true !== $this->cache->set('counter', $this->counter)) {
throw new RuntimeException('Unexpected value: false');
}
}

private function newCache(): Cache
{
$factory = new AdapterFactory(new SerializerFactory());

return new Cache($factory->newInstance('memory'));
}
}
81 changes: 81 additions & 0 deletions tests/benchmarks/Config/ConfigBench.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<?php

/**
* This file is part of the Phalcon Framework.
*
* (c) Phalcon Team <team@phalcon.io>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace Phalcon\Tests\Benchmarks\Config;

use Phalcon\Config\Config;
use Phalcon\Di\Di;
use PhpBench\Attributes\BeforeMethods;
use RuntimeException;

#[BeforeMethods('setUp')]
final class ConfigBench
{
private const DATA = [
'app' => [
'baseUri' => '/',
'name' => 'bench',
'timezone' => 'UTC',
],
'database' => [
'adapter' => 'mysql',
'dbname' => 'phalcon',
'host' => 'localhost',
'options' => [
'charset' => 'utf8mb4',
],
'password' => 'secret',
'port' => 3306,
'username' => 'root',
],
'services' => [
'cache' => 'memory',
'logger' => 'stream',
'mailer' => 'smtp',
'queue' => 'beanstalk',
'session' => 'files',
],
];

private Config $config;

public function setUp(): void
{
Di::reset();

$this->config = new Config(self::DATA);
}

/**
* A new config from a nested array, as one request makes it: each
* nested array becomes a Config object.
*/
public function benchConstruct(): void
{
$config = new Config(self::DATA);

$actual = $config->path('database.options.charset');
if ('utf8mb4' !== $actual) {
throw new RuntimeException(sprintf('Unexpected value: %s', var_export($actual, true)));
}
}

public function benchPath(): void
{
$actual = $this->config->path('database.host');

if ('localhost' !== $actual) {
throw new RuntimeException(sprintf('Unexpected value: %s', var_export($actual, true)));
}
}
}
78 changes: 78 additions & 0 deletions tests/benchmarks/Encryption/JwtBench.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<?php

/**
* This file is part of the Phalcon Framework.
*
* (c) Phalcon Team <team@phalcon.io>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace Phalcon\Tests\Benchmarks\Encryption;

use Phalcon\Di\Di;
use Phalcon\Encryption\Security\JWT\Builder;
use Phalcon\Encryption\Security\JWT\Signer\Hmac;
use Phalcon\Encryption\Security\JWT\Token\Parser;
use PhpBench\Attributes\BeforeMethods;
use PhpBench\Attributes\Revs;
use RuntimeException;

/**
* The time claims are fixed, so the token is the same on each call.
*/
#[BeforeMethods('setUp')]
#[Revs(200)]
final class JwtBench
{
private const EXPECTED_TOKEN = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9'
. '.eyJhdWQiOlsiaHR0cHM6Ly9waGFsY29uLmlvIl0sImV4cCI6NDEwMjQ0NDgwMCwianRpIjoiYmVuY2gtMSIsImlhdCI6'
. 'MTcwMDAwMDAwMCwiaXNzIjoiaHR0cHM6Ly9waGFsY29uLmlvIiwibmJmIjoxNzAwMDAwMDAwLCJzdWIiOiJiZW5jaCJ9'
. '.F_CWXOsTMdZz_bXLYj9MxwpfcpXUNZrPCob1zR0AHwWqoHr2yNNTVgji7L7AfVnWAXtxcEn0usXWdxwkKVE3rQ';

private const PASSPHRASE = 'Phalcon!Bench#Passphrase2026';

private Parser $parser;

private Hmac $signer;

public function setUp(): void
{
Di::reset();

$this->parser = new Parser();
$this->signer = new Hmac();
}

public function benchBuild(): void
{
$builder = new Builder($this->signer);
$builder
->setAudience('https://phalcon.io')
->setExpirationTime(4102444800)
->setId('bench-1')
->setIssuedAt(1700000000)
->setIssuer('https://phalcon.io')
->setNotBefore(1700000000)
->setPassphrase(self::PASSPHRASE)
->setSubject('bench');

$actual = $builder->getToken()->getToken();

if (self::EXPECTED_TOKEN !== $actual) {
throw new RuntimeException(sprintf('Unexpected value: "%s"', $actual));
}
}

public function benchParse(): void
{
$actual = $this->parser->parse(self::EXPECTED_TOKEN)->getClaims()->get('sub');

if ('bench' !== $actual) {
throw new RuntimeException(sprintf('Unexpected value: %s', var_export($actual, true)));
}
}
}
Loading
Loading