OpenApiModuleTest.php 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. <?php
  2. namespace App\Module\OpenAPI\Tests;
  3. use App\Module\OpenAPI\Models\OpenApiApp;
  4. use App\Module\OpenAPI\Services\OpenApiService;
  5. use App\Module\OpenAPI\Services\RateLimitService;
  6. use App\Module\OpenAPI\Services\ScopeService;
  7. use App\Module\OpenAPI\Services\WebhookService;
  8. use Illuminate\Foundation\Testing\RefreshDatabase;
  9. use Illuminate\Foundation\Testing\WithFaker;
  10. use Tests\TestCase;
  11. /**
  12. * OpenAPI模块测试
  13. */
  14. class OpenApiModuleTest extends TestCase
  15. {
  16. use RefreshDatabase, WithFaker;
  17. protected OpenApiService $openApiService;
  18. protected RateLimitService $rateLimitService;
  19. protected ScopeService $scopeService;
  20. protected WebhookService $webhookService;
  21. protected function setUp(): void
  22. {
  23. parent::setUp();
  24. $this->openApiService = app(OpenApiService::class);
  25. $this->rateLimitService = app(RateLimitService::class);
  26. $this->scopeService = app(ScopeService::class);
  27. $this->webhookService = app(WebhookService::class);
  28. }
  29. /**
  30. * 测试创建应用
  31. */
  32. public function test_create_app()
  33. {
  34. $appData = [
  35. 'name' => 'Test App',
  36. 'description' => 'This is a test application',
  37. 'website' => 'https://example.com',
  38. 'callback_url' => 'https://example.com/callback',
  39. 'contact_email' => 'test@example.com',
  40. 'user_id' => 1,
  41. ];
  42. $app = $this->openApiService->createApp($appData);
  43. $this->assertInstanceOf(OpenApiApp::class, $app);
  44. $this->assertEquals($appData['name'], $app->name);
  45. $this->assertEquals($appData['description'], $app->description);
  46. $this->assertNotEmpty($app->app_id);
  47. $this->assertNotEmpty($app->app_secret);
  48. $this->assertEquals(32, strlen($app->app_id));
  49. $this->assertEquals(64, strlen($app->app_secret));
  50. }
  51. /**
  52. * 测试应用认证
  53. */
  54. public function test_app_authentication()
  55. {
  56. // 创建测试应用
  57. $app = $this->createTestApp();
  58. // 测试正确的认证
  59. $authenticatedApp = $this->openApiService->authenticateApp($app->app_id, $app->app_secret);
  60. $this->assertInstanceOf(OpenApiApp::class, $authenticatedApp);
  61. $this->assertEquals($app->app_id, $authenticatedApp->app_id);
  62. // 测试错误的密钥
  63. $result = $this->openApiService->authenticateApp($app->app_id, 'wrong_secret');
  64. $this->assertNull($result);
  65. // 测试不存在的应用ID
  66. $result = $this->openApiService->authenticateApp('nonexistent_app_id', $app->app_secret);
  67. $this->assertNull($result);
  68. }
  69. /**
  70. * 测试权限范围验证
  71. */
  72. public function test_scope_validation()
  73. {
  74. $app = $this->createTestApp(['scopes' => ['USER_READ', 'GAME_READ']]);
  75. // 测试拥有的权限
  76. $this->assertTrue($this->scopeService->hasScope($app, 'USER_READ'));
  77. $this->assertTrue($this->scopeService->hasScope($app, 'GAME_READ'));
  78. // 测试没有的权限
  79. $this->assertFalse($this->scopeService->hasScope($app, 'USER_WRITE'));
  80. $this->assertFalse($this->scopeService->hasScope($app, 'ADMIN_READ'));
  81. // 测试管理员权限
  82. $adminApp = $this->createTestApp(['scopes' => ['ADMIN']]);
  83. $this->assertTrue($this->scopeService->hasScope($adminApp, 'USER_READ'));
  84. $this->assertTrue($this->scopeService->hasScope($adminApp, 'USER_WRITE'));
  85. $this->assertTrue($this->scopeService->hasScope($adminApp, 'ADMIN_READ'));
  86. }
  87. /**
  88. * 测试频率限制
  89. */
  90. public function test_rate_limiting()
  91. {
  92. $app = $this->createTestApp([
  93. 'rate_limits' => [
  94. 'requests_per_minute' => 5,
  95. 'requests_per_hour' => 100,
  96. ]
  97. ]);
  98. $request = $this->createMockRequest();
  99. // 测试正常请求
  100. for ($i = 0; $i < 5; $i++) {
  101. $result = $this->rateLimitService->checkRateLimit($app, $request);
  102. $this->assertTrue($result['allowed']);
  103. }
  104. // 测试超出限制
  105. $result = $this->rateLimitService->checkRateLimit($app, $request);
  106. $this->assertFalse($result['allowed']);
  107. $this->assertEquals('requests_per_minute', $result['limit_type']);
  108. }
  109. /**
  110. * 测试Webhook创建
  111. */
  112. public function test_webhook_creation()
  113. {
  114. $app = $this->createTestApp();
  115. $webhookData = [
  116. 'name' => 'Test Webhook',
  117. 'url' => 'https://example.com/webhook',
  118. 'events' => ['user.created', 'user.updated'],
  119. 'timeout' => 30,
  120. 'retry_count' => 3,
  121. ];
  122. $webhook = $this->webhookService->createWebhook($app, $webhookData);
  123. $this->assertEquals($webhookData['name'], $webhook->name);
  124. $this->assertEquals($webhookData['url'], $webhook->url);
  125. $this->assertEquals($webhookData['events'], $webhook->events);
  126. $this->assertEquals($app->app_id, $webhook->app_id);
  127. $this->assertNotEmpty($webhook->secret);
  128. }
  129. /**
  130. * 测试应用状态检查
  131. */
  132. public function test_app_status_checks()
  133. {
  134. // 测试激活状态
  135. $activeApp = $this->createTestApp(['status' => 'ACTIVE']);
  136. $this->assertTrue($activeApp->isActive());
  137. $this->assertFalse($activeApp->isSuspended());
  138. $this->assertFalse($activeApp->isExpired());
  139. // 测试暂停状态
  140. $suspendedApp = $this->createTestApp(['status' => 'SUSPENDED']);
  141. $this->assertFalse($suspendedApp->isActive());
  142. $this->assertTrue($suspendedApp->isSuspended());
  143. // 测试过期状态
  144. $expiredApp = $this->createTestApp([
  145. 'status' => 'ACTIVE',
  146. 'expires_at' => now()->subDay()
  147. ]);
  148. $this->assertTrue($expiredApp->isActive());
  149. $this->assertTrue($expiredApp->isExpired());
  150. }
  151. /**
  152. * 测试IP白名单
  153. */
  154. public function test_ip_whitelist()
  155. {
  156. $app = $this->createTestApp([
  157. 'ip_whitelist' => ['192.168.1.1', '10.0.0.0/8', '172.16.*']
  158. ]);
  159. // 测试精确匹配
  160. $this->assertTrue($app->isIpAllowed('192.168.1.1'));
  161. $this->assertFalse($app->isIpAllowed('192.168.1.2'));
  162. // 测试CIDR匹配
  163. $this->assertTrue($app->isIpAllowed('10.0.0.1'));
  164. $this->assertTrue($app->isIpAllowed('10.255.255.255'));
  165. $this->assertFalse($app->isIpAllowed('11.0.0.1'));
  166. // 测试通配符匹配
  167. $this->assertTrue($app->isIpAllowed('172.16.1'));
  168. $this->assertTrue($app->isIpAllowed('172.16.255'));
  169. $this->assertFalse($app->isIpAllowed('172.17.1'));
  170. // 测试无白名单(允许所有)
  171. $noWhitelistApp = $this->createTestApp(['ip_whitelist' => null]);
  172. $this->assertTrue($noWhitelistApp->isIpAllowed('1.2.3.4'));
  173. }
  174. /**
  175. * 测试统计数据生成
  176. */
  177. public function test_stats_generation()
  178. {
  179. $app = $this->createTestApp();
  180. // 模拟API调用日志
  181. $this->createTestLogs($app, 10);
  182. // 获取统计数据
  183. $stats = $this->openApiService->getAppStats($app->app_id, 'day');
  184. $this->assertIsArray($stats);
  185. $this->assertArrayHasKey('total_requests', $stats);
  186. $this->assertArrayHasKey('total_success', $stats);
  187. $this->assertArrayHasKey('total_errors', $stats);
  188. $this->assertArrayHasKey('success_rate', $stats);
  189. }
  190. /**
  191. * 创建测试应用
  192. */
  193. protected function createTestApp(array $overrides = []): OpenApiApp
  194. {
  195. $defaultData = [
  196. 'name' => $this->faker->company,
  197. 'description' => $this->faker->sentence,
  198. 'website' => $this->faker->url,
  199. 'callback_url' => $this->faker->url,
  200. 'contact_email' => $this->faker->email,
  201. 'user_id' => 1,
  202. 'status' => 'ACTIVE',
  203. 'auth_type' => 'API_KEY',
  204. 'scopes' => ['USER_READ', 'GAME_READ'],
  205. ];
  206. $data = array_merge($defaultData, $overrides);
  207. return $this->openApiService->createApp($data);
  208. }
  209. /**
  210. * 创建模拟请求
  211. */
  212. protected function createMockRequest()
  213. {
  214. $request = new \Illuminate\Http\Request();
  215. $request->server->set('REMOTE_ADDR', '127.0.0.1');
  216. $request->server->set('REQUEST_URI', '/api/test');
  217. return $request;
  218. }
  219. /**
  220. * 创建测试日志
  221. */
  222. protected function createTestLogs(OpenApiApp $app, int $count = 10)
  223. {
  224. for ($i = 0; $i < $count; $i++) {
  225. \App\Module\OpenAPI\Models\OpenApiLog::create([
  226. 'app_id' => $app->app_id,
  227. 'user_id' => 1,
  228. 'method' => 'GET',
  229. 'uri' => '/api/test',
  230. 'params' => json_encode(['test' => 'data']),
  231. 'headers' => json_encode(['User-Agent' => 'Test']),
  232. 'ip_address' => '127.0.0.1',
  233. 'user_agent' => 'Test Agent',
  234. 'response_code' => $i < 8 ? 200 : 400, // 80%成功率
  235. 'response_time' => rand(100, 1000),
  236. 'response_size' => rand(1000, 5000),
  237. 'scope' => 'USER_READ',
  238. 'rate_limit_hit' => false,
  239. ]);
  240. }
  241. }
  242. }