Skip to content

Commit 0c959df

Browse files
Merge pull request #9553 from eoioer/master
[PHP] Add cyberphp tests
2 parents 27012ed + d5f024c commit 0c959df

20 files changed

+1322
-0
lines changed

frameworks/PHP/cyberphp/README.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# CyberPHP Benchmarking Test
2+
3+
## Test URLs
4+
### JSON
5+
6+
http://localhost:8080/json
7+
8+
### PLAINTEXT
9+
10+
http://localhost:8080/plaintext
11+
12+
### DB
13+
14+
http://localhost:8080/db
15+
16+
### QUERY
17+
18+
http://localhost:8080/queries/[count]
19+
20+
### UPDATE
21+
22+
http://localhost:8080/updates/[count]
23+
24+
### FORTUNES
25+
26+
http://localhost:8080/fortunes
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php
2+
return [
3+
'app_name' => 'Cyber',
4+
// Request middleware runs after obtaining request body and before parsing route
5+
// Mainly used for blacklist, whitelist, system maintenance, request filtering, data access, etc.
6+
'request_middleware' => [
7+
// \app\common\middleware\IpBlacklistMiddleware::class,// IP blacklist middleware
8+
// \app\middleware\RateLimitMiddleware::class,// Rate limit middleware
9+
// \app\middleware\SecurityMiddleware::class, // Security protection (CSRF/XSS filtering/SQL injection) middleware
10+
],
11+
// Business middleware runs after parsing route and before executing controller method
12+
// Mainly used for common business such as user authentication
13+
'middleware' => [
14+
// \app\common\middleware\Route1Middleware::class,
15+
// \app\common\middleware\Route2Middleware::class,
16+
],
17+
'orm' => 'pdo',
18+
'pdo' => [
19+
'dsn' => 'pgsql:host=tfb-database;dbname=hello_world',
20+
'username' => 'benchmarkdbuser',
21+
'password' => 'benchmarkdbpass',
22+
'options' => [PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,PDO::ATTR_EMULATE_PREPARES => false]
23+
],
24+
'eloquent' => [
25+
'driver' => 'mysql',
26+
'host' => '127.0.0.1',
27+
'database' => 'lavaman',
28+
'username' => 'root',
29+
'password' => 'root',
30+
'charset' => 'utf8mb4',
31+
'prefix' => '',
32+
],
33+
'thinkorm' => [
34+
'default' => 'mysql',
35+
'connections' => [
36+
'mysql' => [
37+
'type' => 'mysql', // Database type
38+
'hostname' => '127.0.0.1',// Server address
39+
'database' => 'lavaman',// Database name
40+
'username' => 'root',// Database username
41+
'password' => 'root',// Database password
42+
'hostport' => '',// Database connection port
43+
'params' => [],
44+
'charset' => 'utf8mb4',// Database encoding default utf8
45+
'prefix' => '',// Table prefix
46+
],
47+
],
48+
],
49+
'cookie' => [
50+
'expires' => 0,
51+
'path' => '/',
52+
'domain' => '',
53+
'secure' => true,
54+
'httponly' => true,
55+
'samesite' => 'Lax' // None, Lax, Strict
56+
]
57+
];
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<?php
2+
namespace app\controller;
3+
4+
use Cyber\Response;
5+
class Index {
6+
7+
public function json()
8+
{
9+
return Response::json(['message' => 'Hello, World!']);
10+
}
11+
12+
public function plaintext()
13+
{
14+
return Response::text('Hello, World!');
15+
}
16+
17+
public function db()
18+
{
19+
$prepare = app()->dbWorld;
20+
$prepare->execute([mt_rand(1, 10000)]);
21+
$data = $prepare->fetch();
22+
return Response::json($data);
23+
}
24+
public function fortunes()
25+
{
26+
$fortune = app()->dbFortune;
27+
$fortune->execute();
28+
$arr = $fortune->fetchAll(\PDO::FETCH_KEY_PAIR);
29+
$arr[0] = 'Additional fortune added at request time.';
30+
\asort($arr);
31+
$html = '';
32+
foreach ($arr as $id => $message) {
33+
$message = \htmlspecialchars($message, \ENT_QUOTES, 'UTF-8');
34+
$html .= "<tr><td>$id</td><td>$message</td></tr>";
35+
}
36+
return Response::html("<!DOCTYPE html><html><head><title>Fortunes</title></head><body><table><tr><th>id</th><th>message</th></tr>$html</table></body></html>");
37+
}
38+
39+
public function queries($q=1)
40+
{
41+
$statement = app()->dbWorld;
42+
$query_count = max(min(intval($q), 500), 1);
43+
$arr = [];
44+
while ($query_count--) {
45+
$statement->execute([mt_rand(1, 10000)]);
46+
$arr[] = $statement->fetch();
47+
}
48+
return Response::json($arr);
49+
}
50+
51+
public function updates($q=1)
52+
{
53+
static $updates = [];
54+
55+
$random = app()->dbWorld;
56+
$count = max(min(intval($q), 500), 1);
57+
58+
$worlds = $keys = $values = [];
59+
for ($i = 0; $i < $count; ++ $i) {
60+
$values[] = $keys[] = $id = mt_rand(1, 10000);
61+
$random->execute([$id]);
62+
$row = $random->fetch();
63+
$values[] = $row['randomNumber'] = mt_rand(1, 10000);
64+
$worlds[] = $row;
65+
}
66+
if (!isset($updates[$count])) {
67+
$sql = 'UPDATE World SET randomNumber = CASE id' . str_repeat(' WHEN ?::INTEGER THEN ?::INTEGER ', $count) . 'END WHERE id IN (' . str_repeat('?::INTEGER,', $count - 1) . '?::INTEGER)';
68+
$updates[$count] = app()->db->prepare($sql);
69+
}
70+
$updates[$count]->execute([...$values, ...$keys]);
71+
72+
return Response::json($worlds);
73+
}
74+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
/**
5+
* Get the application instance
6+
* If there is a configuration file, create the application instance
7+
* If there is no configuration file, return the already created instance
8+
* If there is no configuration file and no instance has been created, throw an exception
9+
* @param string $bootstrap Configuration file
10+
* @return \Cyber\App
11+
*/
12+
if (!function_exists('app')) {
13+
function app(): \Cyber\App
14+
{
15+
return \Cyber\App::getInstance();
16+
}
17+
}
18+
19+
/**
20+
* Get configuration information
21+
* config(); // Returns all configurations
22+
* config('app.name'); // Gets the value of app.name
23+
* config('db.mysql.host'); // Gets the value of db.mysql.host
24+
* @param string|null $key Configuration key name, supports multi-level configuration separated by dots, e.g., 'app.debug'
25+
* @param mixed $default Default value, returned when the configuration item does not exist
26+
* @return mixed
27+
*/
28+
if (!function_exists('config')) {
29+
function config(?string $key = null, $default = null)
30+
{
31+
return \Cyber\App::getInstance()->getConfig($key) ?? $default;
32+
}
33+
}
34+
35+
function renderExceptionPage($e, $debug = true, $templateFile = ''): string
36+
{
37+
// Determine template path
38+
$templateFile = !empty($templateFile) ? $templateFile : __DIR__ . '/views/errors/exception.html';
39+
// Prepare template variables
40+
$data = [
41+
'code' => $e->getCode(),
42+
'message' => $debug ? $e->getMessage() : 'The current server is experiencing an error, please contact the administrator or try again later.',
43+
'error' => $e->getMessage(),
44+
];
45+
// Add more information in debug mode
46+
if ($debug) {
47+
$data['trace'] = [];
48+
$data['file'] = $e->getFile();
49+
$data['line'] = $e->getLine();
50+
$traceFiles = $e->getTrace();
51+
array_unshift($traceFiles, ['file' => $data['file'], 'line' => $data['line']]);
52+
foreach ($traceFiles as $v) {
53+
try {
54+
if (isset($v['file']) && isset($v['line'])) {
55+
$startline = max(1, $v['line'] - 10);
56+
$contents = file($v['file']);
57+
$data['trace'][] = [
58+
'file' => $v['file'],
59+
'line' => $v['line'],
60+
'source0' => $contents ? array_slice($contents, 0, 1) : '',
61+
'source' => [
62+
'startline' => $startline,
63+
'content' => array_slice($contents, $startline - 1, 16)
64+
]
65+
];
66+
}
67+
} catch (\Throwable $e) {
68+
continue;
69+
}
70+
}
71+
}
72+
// Render error page
73+
if (!file_exists($templateFile)) {
74+
$msg = '<div style="margin:100px auto 20px;text-align:center"><h1>Error ' . $data['code'] . '</h1></div>';
75+
$msg .= '<div style="margin:0px auto;text-align:center">Sorry, the server encountered an error</div>';
76+
$msg .= '<div style="margin:50px auto;text-align:center"><h2><pre>' . htmlspecialchars($data['message']) . '</pre></h2></div>';
77+
$msg .= '<div style="margin:100px auto;text-align:center"><a href="/"><button>Return to Home</button></a></div>';
78+
return $msg;
79+
}
80+
extract($data);
81+
ob_start();
82+
include $templateFile;
83+
return ob_get_clean();
84+
}

frameworks/PHP/cyberphp/app/route.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
use Cyber\Request;
3+
4+
return [
5+
['/', 'GET', 'app\controller\Index@hello'],
6+
['/json', 'GET', 'app\controller\Index@json'],
7+
['/plaintext', 'GET', 'app\controller\Index@plaintext'],
8+
['/db', 'GET', 'app\controller\Index@db'],
9+
['/fortunes', 'GET', 'app\controller\Index@fortunes'],
10+
['/queries/', 'GET', 'app\controller\Index@queries'],
11+
['/queries/{q}', 'GET', 'app\controller\Index@queries'],
12+
['/updates/', 'GET', 'app\controller\Index@updates'],
13+
['/updates/{q}', 'GET', 'app\controller\Index@updates'],
14+
];
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
4+
<head>
5+
<meta charset="UTF-8">
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
7+
<title>An Error Occurred</title>
8+
<style>
9+
body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;line-height:1.6;margin:0;padding:0;background:#f8f9fa;color:#343a40}
10+
pre{margin:0;padding:0;}
11+
.container{max-width:80%;margin:50px auto;padding:20px;background:#fff;border-radius:8px;box-shadow:0 2px 4px rgba(0,0,0,0.1)}
12+
.error-code{font-size:72px;font-weight:bold;color:#dc3545;margin:0;line-height:1}
13+
.error-title{font-size:24px;color:#495057;margin:20px 0}
14+
.error-message{font-size:16px;color:#6c757d;margin-bottom:30px;padding:15px;background:#f8f9fa;border-radius:4px;border-left:4px solid #dc3545}
15+
.back-link{display:inline-block;margin-top:20px;padding:10px 20px;background:#007bff;color:#fff;text-decoration:none;border-radius:4px;transition:background-color 0.2s}
16+
.back-link:hover{background:#0056b3}
17+
18+
.source-box{margin:10px 0;padding:0px;}
19+
.source-box a{color:#369;font-weight:900;}
20+
.source-file{padding:5px 10px;background:#f8f9fa;}
21+
.source-code{padding:4px 0px;border: 0px solid #ddd;background: #f1f2f3;overflow-x: auto;}
22+
.source-code ol,.source-code ul{margin: 0;color: #555;font-size:14px;}
23+
.source-code code{border-left: 1px solid #ccc;padding-left:5px;font-family: "Consolas";}
24+
.source-error{color:#000;background:#dc354533!important}
25+
.source-error code{font-weight:900;}
26+
</style>
27+
</head>
28+
<body>
29+
<div class="container">
30+
<h1 class="error-code">Error <?php echo htmlspecialchars($code); ?></h1>
31+
<h2 class="error-title">Sorry, an error occurred</h2>
32+
<div class="error-message"><?php echo htmlspecialchars($message); ?></div>
33+
<!-- <?php echo htmlspecialchars($error); ?> -->
34+
<?php if (isset($trace)) { ?>
35+
<?php foreach ($trace as $k => $v) { ?>
36+
<div class="source-box">
37+
<div class="source-file">#<?= $k ?> <a href="view-source:file:///<?php echo $v['file']; ?>"><?php echo $v['file']; ?></a> Line <?php echo $v['line']; ?></div>
38+
<div class="source-code">
39+
<pre><?php
40+
if (!empty($v['source0'])) {
41+
echo '<ol start="0"><li><code>'.htmlentities($v['source0'][0]).'</code></li></ol>';
42+
}
43+
if (!empty($v['source'])) {
44+
echo '<ol start="'.htmlentities($v['source']['startline']).'">';
45+
foreach ((array) $v['source']['content'] as $key => $value) {
46+
if (($key + $v['source']['startline']) == $v['line']) {
47+
echo '<li class="source-error"><code>'.htmlentities($value).'</code></li>';
48+
} else {
49+
echo '<li><code>'.htmlentities($value).'</code></li>';
50+
}
51+
}
52+
echo '</ol>';
53+
}
54+
?></pre>
55+
</div>
56+
</div>
57+
<?php } ?>
58+
<?php } ?>
59+
<a href="/" class="back-link">Return to Home</a>
60+
</body>
61+
62+
</html>
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
"framework": "cyberphp",
3+
"tests": [
4+
{
5+
"default": {
6+
"json_url": "/json",
7+
"db_url": "/db",
8+
"query_url": "/queries/",
9+
"fortune_url": "/fortunes",
10+
"update_url": "/updates/",
11+
"plaintext_url": "/plaintext",
12+
"port": 8080,
13+
"approach": "Realistic",
14+
"classification": "Micro",
15+
"database": "Postgres",
16+
"framework": "cyberphp",
17+
"language": "PHP",
18+
"flavor": "PHP8",
19+
"orm": "Raw",
20+
"platform": "workerman",
21+
"webserver": "None",
22+
"os": "Linux",
23+
"database_os": "Linux",
24+
"display_name": "cyberphp",
25+
"notes": "",
26+
"versus": "workerman"
27+
}
28+
}
29+
]
30+
}

0 commit comments

Comments
 (0)