agent/php/tests/Feature/Mcp/Services/McpQuotaServiceTest.php
Snider 09054fbdab feat(mcp): implement §3 Services (ToolRegistry + McpQuotaService + QueryAuditService + ToolDependencyService) (#851)
Additive-only — no existing files modified.

- ToolRegistry: register/resolve/listTools/buildDependencyGraph
  - Singleton via registerSingleton() entry point (no Boot.php wire-in
    per scope; tests cover the binding path)
- McpQuotaService: workspace-scoped checkQuota/consume/reset
- QueryAuditService: log/query/aggregate (expects mcp_audit_entries
  table; tests create inline as migration was out-of-scope)
- ToolDependencyService: validateDependencies via graph traversal

Data DTOs: ToolMetadata, QuotaResult, AuditEntry as readonly.
Pest Feature tests _Good/_Bad/_Ugly per AX-10.
pest skipped (vendor binaries missing).

Co-authored-by: Codex <noreply@openai.com>
Closes tasks.lthn.sh/view.php?id=851
2026-04-25 05:14:15 +01:00

51 lines
1.6 KiB
PHP

<?php
// SPDX-License-Identifier: EUPL-1.2
declare(strict_types=1);
use Core\Mod\Agentic\Mcp\Services\McpQuotaService;
use Illuminate\Support\Facades\Cache;
beforeEach(function (): void {
Cache::flush();
config()->set('mcp.quota_limit', 3);
config()->set('mcp.quota_period', 'minute');
});
test('McpQuotaService_checkQuota_consume_reset_Good_tracks_workspace_usage_per_period', function (): void {
$service = new McpQuotaService;
$service->setQuota('workspace-alpha', 5);
$initial = $service->checkQuota('workspace-alpha');
$consumed = $service->consume('workspace-alpha', 2);
$reset = $service->reset('workspace-alpha');
expect($initial->used)->toBe(0)
->and($initial->limit)->toBe(5)
->and($consumed->used)->toBe(2)
->and($consumed->remaining)->toBe(3)
->and($consumed->exceeded)->toBeFalse()
->and($reset->used)->toBe(0)
->and($reset->remaining)->toBe(5);
});
test('McpQuotaService_checkQuota_Bad_marks_exhausted_workspaces_as_exceeded', function (): void {
$service = new McpQuotaService;
$service->setQuota('workspace-bravo', 2);
$service->consume('workspace-bravo', 2);
$result = $service->checkQuota('workspace-bravo');
expect($result->used)->toBe(2)
->and($result->remaining)->toBe(0)
->and($result->exceeded)->toBeTrue();
});
test('McpQuotaService_consume_Ugly_rejects_non_positive_usage_units', function (): void {
$service = new McpQuotaService;
$service->consume('workspace-charlie', 0);
})->throws(InvalidArgumentException::class, 'Quota consumption units must be at least 1.');