1 | <?php declare(strict_types=1); |
||||
2 | |||||
3 | /* |
||||
4 | * This file is part of Flight Routing. |
||||
5 | * |
||||
6 | * PHP version 8.0 and above required |
||||
7 | * |
||||
8 | * @author Divine Niiquaye Ibok <[email protected]> |
||||
9 | * @copyright 2019 Divine Niiquaye Ibok (https://divinenii.com/) |
||||
10 | * @license https://opensource.org/licenses/BSD-3-Clause License |
||||
11 | * |
||||
12 | * For the full copyright and license information, please view the LICENSE |
||||
13 | * file that was distributed with this source code. |
||||
14 | */ |
||||
15 | |||||
16 | namespace Flight\Routing\Tests\Benchmarks; |
||||
17 | |||||
18 | use Flight\Routing\Exceptions\MethodNotAllowedException; |
||||
19 | use Flight\Routing\Interfaces\RouteMatcherInterface; |
||||
20 | use Nyholm\Psr7\Uri; |
||||
21 | |||||
22 | /** |
||||
23 | * @Warmup(2) |
||||
24 | * @Revs(100) |
||||
25 | * @Iterations(5) |
||||
26 | * @BeforeClassMethods({"before"}) |
||||
27 | */ |
||||
28 | abstract class RouteBench |
||||
29 | { |
||||
30 | protected const MAX_ROUTES = 400; |
||||
31 | protected const CACHE_FILE = __DIR__.'/../Fixtures/compiled_test.php'; |
||||
32 | |||||
33 | /** @var array<string,RouteMatcherInterface> */ |
||||
34 | private array $dispatchers = []; |
||||
35 | |||||
36 | public static function before(): void |
||||
37 | { |
||||
38 | if (\file_exists(self::CACHE_FILE)) { |
||||
39 | @\unlink(self::CACHE_FILE); |
||||
0 ignored issues
–
show
|
|||||
40 | } |
||||
41 | } |
||||
42 | |||||
43 | /** @return \Generator<string,array<string,mixed>> */ |
||||
44 | abstract public function provideStaticRoutes(): iterable; |
||||
45 | |||||
46 | /** @return \Generator<string,array<string,mixed>> */ |
||||
47 | abstract public function provideDynamicRoutes(): iterable; |
||||
48 | |||||
49 | /** @return \Generator<string,array<string,mixed>> */ |
||||
50 | abstract public function provideOtherScenarios(): iterable; |
||||
51 | |||||
52 | /** @return \Generator<string,array<int,mixed>> */ |
||||
53 | public function provideAllScenarios(): iterable |
||||
54 | { |
||||
55 | yield 'static(first,middle,last,invalid-method)' => \array_values(\iterator_to_array($this->provideStaticRoutes())); |
||||
56 | yield 'dynamic(first,middle,last,invalid-method)' => \array_values(\iterator_to_array($this->provideDynamicRoutes())); |
||||
57 | yield 'others(non-existent,...)' => \array_values(\iterator_to_array($this->provideOtherScenarios())); |
||||
58 | } |
||||
59 | |||||
60 | /** @return \Generator<string,array<string,string>> */ |
||||
61 | public function provideDispatcher(): iterable |
||||
62 | { |
||||
63 | yield 'not_cached' => ['dispatcher' => 'not_cached']; |
||||
64 | yield 'cached' => ['dispatcher' => 'cached']; |
||||
65 | } |
||||
66 | |||||
67 | public function initDispatchers(): void |
||||
68 | { |
||||
69 | $this->dispatchers['not_cached'] = $this->createDispatcher(); |
||||
70 | $this->dispatchers['cached'] = $this->createDispatcher(self::CACHE_FILE); |
||||
71 | } |
||||
72 | |||||
73 | /** |
||||
74 | * @BeforeMethods({"initDispatchers"}) |
||||
75 | * @ParamProviders({"provideDispatcher", "provideStaticRoutes"}) |
||||
76 | */ |
||||
77 | public function benchStaticRoutes(array $params): void |
||||
78 | { |
||||
79 | $this->runScenario($params); |
||||
80 | } |
||||
81 | |||||
82 | /** |
||||
83 | * @BeforeMethods({"initDispatchers"}) |
||||
84 | * @ParamProviders({"provideDispatcher", "provideDynamicRoutes"}) |
||||
85 | */ |
||||
86 | public function benchDynamicRoutes(array $params): void |
||||
87 | { |
||||
88 | $this->runScenario($params); |
||||
89 | } |
||||
90 | |||||
91 | /** |
||||
92 | * @BeforeMethods({"initDispatchers"}) |
||||
93 | * @ParamProviders({"provideDispatcher", "provideOtherScenarios"}) |
||||
94 | */ |
||||
95 | public function benchOtherRoutes(array $params): void |
||||
96 | { |
||||
97 | $this->runScenario($params); |
||||
98 | } |
||||
99 | |||||
100 | /** |
||||
101 | * @BeforeMethods({"initDispatchers"}) |
||||
102 | * @ParamProviders({"provideDispatcher", "provideAllScenarios"}) |
||||
103 | */ |
||||
104 | public function benchAll(array $params): void |
||||
105 | { |
||||
106 | $dispatcher = \array_shift($params); |
||||
107 | |||||
108 | foreach ($params as $param) { |
||||
109 | $this->runScenario($param + \compact('dispatcher')); |
||||
110 | } |
||||
111 | } |
||||
112 | |||||
113 | /** |
||||
114 | * @ParamProviders({"provideAllScenarios"}) |
||||
115 | * @Revs(4) |
||||
116 | */ |
||||
117 | public function benchWithRouter(array $params): void |
||||
118 | { |
||||
119 | $this->dispatchers['router'] = $this->createDispatcher(); |
||||
120 | |||||
121 | foreach ($params as $param) { |
||||
122 | $this->runScenario($param + ['dispatcher' => 'router']); |
||||
123 | } |
||||
124 | } |
||||
125 | |||||
126 | /** |
||||
127 | * @ParamProviders({"provideAllScenarios"}) |
||||
128 | * @Revs(4) |
||||
129 | */ |
||||
130 | public function benchWithCache(array $params): void |
||||
131 | { |
||||
132 | $this->dispatchers['cached'] = $this->createDispatcher(self::CACHE_FILE); |
||||
133 | |||||
134 | foreach ($params as $param) { |
||||
135 | $this->runScenario($param + ['dispatcher' => 'cached']); |
||||
136 | } |
||||
137 | } |
||||
138 | |||||
139 | abstract protected function createDispatcher(string $cache = null): RouteMatcherInterface; |
||||
140 | |||||
141 | /** |
||||
142 | * @param array<string,array<int,mixed>|string> $params |
||||
143 | */ |
||||
144 | private function runScenario(array $params): void |
||||
145 | { |
||||
146 | try { |
||||
147 | $dispatcher = $this->dispatchers[$params['dispatcher']]; |
||||
148 | $result = $params['result'] === $dispatcher->match($params['method'], new Uri($params['route'])); |
||||
0 ignored issues
–
show
It seems like
$params['route'] can also be of type array<integer,mixed> ; however, parameter $uri of Nyholm\Psr7\Uri::__construct() does only seem to accept string , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
149 | } catch (MethodNotAllowedException $e) { |
||||
150 | $result = $params['result'] === $e::class; |
||||
151 | } |
||||
152 | |||||
153 | \assert($result, new \RuntimeException( |
||||
154 | \sprintf( |
||||
155 | 'Benchmark "%s: %s" failed with method "%s"', |
||||
156 | $params['dispatcher'], |
||||
0 ignored issues
–
show
It seems like
$params['dispatcher'] can also be of type array<integer,mixed> ; however, parameter $values of sprintf() does only seem to accept double|integer|string , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
157 | $params['route'], |
||||
158 | $params['method'] |
||||
159 | ) |
||||
160 | )); |
||||
161 | } |
||||
162 | } |
||||
163 |
If you suppress an error, we recommend checking for the error condition explicitly: