176 行
6.1 KiB
PHP
176 行
6.1 KiB
PHP
<?php
|
|
/**
|
|
* Webhook 单元测试
|
|
*/
|
|
require_once __DIR__ . '/../application/common/library/WebhookHandler.php';
|
|
|
|
class WebhookTest
|
|
{
|
|
private $passed = 0;
|
|
private $failed = 0;
|
|
|
|
public function run()
|
|
{
|
|
echo "=== 开始执行 Webhook 单元测试 (TDD) ===\n";
|
|
$this->testInvalidTokenRejection();
|
|
$this->testUrlTokenAllowed();
|
|
$this->testHeaderTokenAllowed();
|
|
$this->testHmacSha256SignatureAllowed();
|
|
$this->testHubSignature256Allowed();
|
|
$this->testNonPostMethodRejection();
|
|
$this->testPingEventSuccess();
|
|
$this->testIgnoredBranchSkipped();
|
|
$this->testTargetBranchTriggersDeploy();
|
|
|
|
echo "\n测试结果: {$this->passed} 通过, {$this->failed} 失败\n";
|
|
if ($this->failed > 0) {
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
private function assert($condition, $message)
|
|
{
|
|
if ($condition) {
|
|
echo " [PASS] {$message}\n";
|
|
$this->passed++;
|
|
} else {
|
|
echo " [FAIL] {$message}\n";
|
|
$this->failed++;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 测试非法 Token 被拦截
|
|
*/
|
|
public function testInvalidTokenRejection()
|
|
{
|
|
$handler = new \app\common\library\WebhookHandler('test_secret_123');
|
|
$server = ['REQUEST_METHOD' => 'POST', 'HTTP_X_GITEA_TOKEN' => 'wrong_token'];
|
|
$res = $handler->handle($server, [], '{}');
|
|
|
|
$this->assert($res['code'] === 403, "非法 Token 应返回 HTTP 403");
|
|
$this->assert($res['data']['status'] === 'error', "非法 Token 应返回 error 状态");
|
|
}
|
|
|
|
/**
|
|
* 测试通过 URL 参数传递 Token 允许通过
|
|
*/
|
|
public function testUrlTokenAllowed()
|
|
{
|
|
$handler = new \app\common\library\WebhookHandler('test_secret_123');
|
|
$server = ['REQUEST_METHOD' => 'POST'];
|
|
$get = ['token' => 'test_secret_123'];
|
|
$res = $handler->handle($server, $get, json_encode(['ref' => 'refs/heads/master']));
|
|
|
|
$this->assert($res['code'] === 200, "合法 URL Token 应返回 HTTP 200");
|
|
}
|
|
|
|
/**
|
|
* 测试通过 Header 传递 Token 允许通过
|
|
*/
|
|
public function testHeaderTokenAllowed()
|
|
{
|
|
$handler = new \app\common\library\WebhookHandler('test_secret_123');
|
|
$server = ['REQUEST_METHOD' => 'POST', 'HTTP_X_GITEA_TOKEN' => 'test_secret_123'];
|
|
$res = $handler->handle($server, [], json_encode(['ref' => 'refs/heads/master']));
|
|
|
|
$this->assert($res['code'] === 200, "合法 Header Token 应返回 HTTP 200");
|
|
}
|
|
|
|
/**
|
|
* 测试通过 Gitea HMAC-SHA256 签名校验
|
|
*/
|
|
public function testHmacSha256SignatureAllowed()
|
|
{
|
|
$handler = new \app\common\library\WebhookHandler('test_secret_123');
|
|
$body = json_encode(['ref' => 'refs/heads/master']);
|
|
$sig = hash_hmac('sha256', $body, 'test_secret_123');
|
|
$server = ['REQUEST_METHOD' => 'POST', 'HTTP_X_GITEA_SIGNATURE' => $sig];
|
|
$res = $handler->handle($server, [], $body);
|
|
|
|
$this->assert($res['code'] === 200, "合法 HMAC-SHA256 签名应返回 HTTP 200");
|
|
}
|
|
|
|
/**
|
|
* 测试通过 GitHub/Gitea sha256= 前缀签名校验
|
|
*/
|
|
public function testHubSignature256Allowed()
|
|
{
|
|
$handler = new \app\common\library\WebhookHandler('test_secret_123');
|
|
$body = json_encode(['ref' => 'refs/heads/master']);
|
|
$sig = 'sha256=' . hash_hmac('sha256', $body, 'test_secret_123');
|
|
$server = ['REQUEST_METHOD' => 'POST', 'HTTP_X_HUB_SIGNATURE_256' => $sig];
|
|
$res = $handler->handle($server, [], $body);
|
|
|
|
$this->assert($res['code'] === 200, "合法 X-Hub-Signature-256 签名应返回 HTTP 200");
|
|
}
|
|
|
|
/**
|
|
* 测试非 POST 请求被拒绝
|
|
*/
|
|
public function testNonPostMethodRejection()
|
|
{
|
|
$handler = new \app\common\library\WebhookHandler('test_secret_123');
|
|
$server = ['REQUEST_METHOD' => 'GET'];
|
|
$get = ['token' => 'test_secret_123'];
|
|
$res = $handler->handle($server, $get, '');
|
|
|
|
$this->assert($res['code'] === 405, "非 POST 请求应返回 HTTP 405");
|
|
}
|
|
|
|
/**
|
|
* 测试 Gitea Ping / Test 事件直接响应成功
|
|
*/
|
|
public function testPingEventSuccess()
|
|
{
|
|
$handler = new \app\common\library\WebhookHandler('test_secret_123');
|
|
$server = [
|
|
'REQUEST_METHOD' => 'POST',
|
|
'HTTP_X_GITEA_EVENT' => 'ping',
|
|
'HTTP_X_GITEA_TOKEN' => 'test_secret_123'
|
|
];
|
|
$res = $handler->handle($server, [], '{}');
|
|
|
|
$this->assert($res['code'] === 200, "Ping 事件应返回 HTTP 200");
|
|
$this->assert($res['data']['message'] === 'pong', "Ping 事件应返回 pong 响应");
|
|
}
|
|
|
|
/**
|
|
* 测试非目标分支推送被跳过
|
|
*/
|
|
public function testIgnoredBranchSkipped()
|
|
{
|
|
$handler = new \app\common\library\WebhookHandler('test_secret_123', 'master');
|
|
$server = ['REQUEST_METHOD' => 'POST', 'HTTP_X_GITEA_TOKEN' => 'test_secret_123'];
|
|
$body = json_encode(['ref' => 'refs/heads/feature_test']);
|
|
$res = $handler->handle($server, [], $body);
|
|
|
|
$this->assert($res['code'] === 200, "非目标分支应返回 HTTP 200");
|
|
$this->assert($res['data']['status'] === 'skipped', "非目标分支状态应为 skipped");
|
|
}
|
|
|
|
/**
|
|
* 测试目标分支推送正确触发部署回调
|
|
*/
|
|
public function testTargetBranchTriggersDeploy()
|
|
{
|
|
$triggered = false;
|
|
$handler = new \app\common\library\WebhookHandler('test_secret_123', 'master', function () use (&$triggered) {
|
|
$triggered = true;
|
|
return "Deploy OK";
|
|
});
|
|
|
|
$server = ['REQUEST_METHOD' => 'POST', 'HTTP_X_GITEA_TOKEN' => 'test_secret_123'];
|
|
$body = json_encode(['ref' => 'refs/heads/master']);
|
|
$res = $handler->handle($server, [], $body);
|
|
|
|
$this->assert($res['code'] === 200, "目标分支应返回 HTTP 200");
|
|
$this->assert($triggered === true, "目标分支必须触发部署回调");
|
|
$this->assert($res['data']['status'] === 'success', "部署状态应为 success");
|
|
$this->assert($res['data']['output'] === 'Deploy OK', "返回内容应包含部署输出");
|
|
}
|
|
}
|
|
|
|
$test = new WebhookTest();
|
|
$test->run();
|