사내/사외 모드 회귀 보강: 전환 즉시반영 및 URL 경계 테스트 추가
Some checks failed
Release Gate / gate (push) Has been cancelled
Some checks failed
Release Gate / gate (push) Has been cancelled
- OperationModePolicyTests에 IsExternalUrl 경계 케이스(http/https vs file/mailto) 추가 - OperationModeReadinessTests 정비 및 internal→external 전환 즉시반영 테스트 추가 - README/DEVELOPMENT 이력(2026-04-04 16:24 KST) 동기화
This commit is contained in:
@@ -31,6 +31,16 @@ public class OperationModePolicyTests
|
||||
OperationModePolicy.IsBlockedAgentToolInInternalMode("open_external", @"E:\work\report.html").Should().BeFalse();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsExternalUrl_DetectsOnlyHttpSchemes()
|
||||
{
|
||||
OperationModePolicy.IsExternalUrl("https://example.com").Should().BeTrue();
|
||||
OperationModePolicy.IsExternalUrl("http://intranet.local").Should().BeTrue();
|
||||
OperationModePolicy.IsExternalUrl(@"E:\work\report.html").Should().BeFalse();
|
||||
OperationModePolicy.IsExternalUrl("mailto:admin@example.com").Should().BeFalse();
|
||||
OperationModePolicy.IsExternalUrl("not-a-url").Should().BeFalse();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AgentContext_CheckToolPermissionAsync_BlocksRestrictedToolsInInternalMode()
|
||||
{
|
||||
|
||||
90
src/AxCopilot.Tests/Services/OperationModeReadinessTests.cs
Normal file
90
src/AxCopilot.Tests/Services/OperationModeReadinessTests.cs
Normal file
@@ -0,0 +1,90 @@
|
||||
using System.Text.Json;
|
||||
using AxCopilot.Handlers;
|
||||
using AxCopilot.Services;
|
||||
using AxCopilot.Services.Agent;
|
||||
using FluentAssertions;
|
||||
using Xunit;
|
||||
|
||||
namespace AxCopilot.Tests.Services;
|
||||
|
||||
public class OperationModeReadinessTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task WebSearch_InternalMode_ShowsBlockedMessage()
|
||||
{
|
||||
var settings = new SettingsService();
|
||||
settings.Settings.OperationMode = OperationModePolicy.InternalMode;
|
||||
var handler = new WebSearchHandler(settings);
|
||||
|
||||
var items = (await handler.GetItemsAsync("ax copilot", CancellationToken.None)).ToList();
|
||||
|
||||
items.Should().NotBeEmpty();
|
||||
items[0].Title.Should().Contain("차단");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task WebSearch_ExternalMode_ReturnsSearchItems()
|
||||
{
|
||||
var settings = new SettingsService();
|
||||
settings.Settings.OperationMode = OperationModePolicy.ExternalMode;
|
||||
var handler = new WebSearchHandler(settings);
|
||||
|
||||
var items = (await handler.GetItemsAsync("ax copilot", CancellationToken.None)).ToList();
|
||||
|
||||
items.Should().NotBeEmpty();
|
||||
items.Any(i => i.Title.Contains("검색")).Should().BeTrue();
|
||||
items.Any(i => i.Title.Contains("차단")).Should().BeFalse();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task WebSearch_ModeSwitch_InternalToExternal_ShouldReflectImmediately()
|
||||
{
|
||||
var settings = new SettingsService();
|
||||
var handler = new WebSearchHandler(settings);
|
||||
|
||||
settings.Settings.OperationMode = OperationModePolicy.InternalMode;
|
||||
var internalItems = (await handler.GetItemsAsync("ax copilot", CancellationToken.None)).ToList();
|
||||
|
||||
settings.Settings.OperationMode = OperationModePolicy.ExternalMode;
|
||||
var externalItems = (await handler.GetItemsAsync("ax copilot", CancellationToken.None)).ToList();
|
||||
|
||||
internalItems.Should().NotBeEmpty();
|
||||
externalItems.Should().NotBeEmpty();
|
||||
internalItems[0].Title.Should().Contain("차단");
|
||||
externalItems.Any(i => i.Title.Contains("검색")).Should().BeTrue();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task HttpTool_InternalMode_IsBlockedEvenWhenCalledDirectly()
|
||||
{
|
||||
var tool = new HttpTool();
|
||||
using var doc = JsonDocument.Parse("""{"method":"GET","url":"http://127.0.0.1:8080/health"}""");
|
||||
var context = new AgentContext
|
||||
{
|
||||
OperationMode = OperationModePolicy.InternalMode,
|
||||
Permission = "Auto"
|
||||
};
|
||||
|
||||
var result = await tool.ExecuteAsync(doc.RootElement, context, CancellationToken.None);
|
||||
|
||||
result.Success.Should().BeFalse();
|
||||
result.Output.Should().Contain("사내모드");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task OpenExternal_InternalMode_BlocksExternalUrl()
|
||||
{
|
||||
var tool = new OpenExternalTool();
|
||||
using var doc = JsonDocument.Parse("""{"path":"https://example.com"}""");
|
||||
var context = new AgentContext
|
||||
{
|
||||
OperationMode = OperationModePolicy.InternalMode,
|
||||
Permission = "Auto"
|
||||
};
|
||||
|
||||
var result = await tool.ExecuteAsync(doc.RootElement, context, CancellationToken.None);
|
||||
|
||||
result.Success.Should().BeFalse();
|
||||
result.Output.Should().Contain("사내모드");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user