文件
nahaichuan/tests/WebhookTest.php

176 行
6.1 KiB
PHP

<?php
/**
* Webhook 单元测试 (TDD 模式)
*/
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();