db620d33df
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
dotnet-build-and-test / dotnet-test-functions (push) Has been cancelled
dotnet-build-and-test / paths-filter (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Debug, windows-latest, net9.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Release, ubuntu-latest, net10.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Release, ubuntu-latest, net8.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Release, windows-latest, net472) (push) Has been cancelled
dotnet-build-and-test / dotnet-test (Release, integration, true, ubuntu-latest, net10.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-test (Release, integration, true, windows-latest, net472) (push) Has been cancelled
dotnet-build-and-test / dotnet-foundry-hosted-it (push) Has been cancelled
dotnet-build-and-test / dotnet-build-and-test-check (push) Has been cancelled
dotnet-build-and-test / Integration Test Report (push) Has been cancelled
103 lines
4.2 KiB
C#
103 lines
4.2 KiB
C#
// Copyright (c) Microsoft. All rights reserved.
|
|
|
|
using System.IO;
|
|
using System.Linq;
|
|
using Microsoft.Agents.AI.LocalCodeAct.Internal;
|
|
using Microsoft.Extensions.AI;
|
|
|
|
namespace Microsoft.Agents.AI.LocalCodeAct.UnitTests;
|
|
|
|
/// <summary>
|
|
/// Unit tests for <see cref="FileMountHelper"/> covering the capture-limit branches
|
|
/// (per-file, per-mount, and total) that produce textual omission placeholders
|
|
/// instead of <see cref="DataContent"/>.
|
|
/// </summary>
|
|
public sealed class FileMountHelperTests
|
|
{
|
|
[Fact]
|
|
public void CaptureWrittenFiles_PerFileLimit_ReturnsTextPlaceholder()
|
|
{
|
|
var dir = Directory.CreateTempSubdirectory("fmh-perfile-").FullName;
|
|
try
|
|
{
|
|
var mount = FileMountHelper.Normalize(new FileMount(dir, "/output", FileMountMode.ReadWrite));
|
|
var pre = FileMountHelper.SnapshotWritableMounts(new[] { mount });
|
|
|
|
File.WriteAllBytes(Path.Combine(dir, "big.bin"), new byte[2048]);
|
|
|
|
// Per-file limit of 1024 bytes — file is 2048 -> should be omitted via TextContent.
|
|
var limits = new ProcessExecutionLimits { MaxCapturedFileBytes = 1024 };
|
|
var captured = FileMountHelper.CaptureWrittenFiles(new[] { mount }, pre, limits);
|
|
|
|
var text = Assert.Single(captured.OfType<TextContent>());
|
|
Assert.Contains("/output/big.bin", text.Text);
|
|
Assert.Contains("per-file capture limit", text.Text);
|
|
Assert.Empty(captured.OfType<DataContent>());
|
|
}
|
|
finally
|
|
{
|
|
Directory.Delete(dir, recursive: true);
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void CaptureWrittenFiles_PerMountLimit_OmitsSecondFile()
|
|
{
|
|
var dir = Directory.CreateTempSubdirectory("fmh-permount-").FullName;
|
|
try
|
|
{
|
|
// WriteBytesLimit caps total bytes captured *for this mount*.
|
|
var mount = FileMountHelper.Normalize(
|
|
new FileMount(dir, "/output", FileMountMode.ReadWrite, writeBytesLimit: 600));
|
|
var pre = FileMountHelper.SnapshotWritableMounts(new[] { mount });
|
|
|
|
// Two files of 400 bytes each — first fits, second exceeds the 600-byte per-mount cap.
|
|
File.WriteAllBytes(Path.Combine(dir, "a.bin"), new byte[400]);
|
|
File.WriteAllBytes(Path.Combine(dir, "b.bin"), new byte[400]);
|
|
|
|
var limits = new ProcessExecutionLimits(); // per-file/total caps high enough not to fire.
|
|
var captured = FileMountHelper.CaptureWrittenFiles(new[] { mount }, pre, limits);
|
|
|
|
Assert.Single(captured.OfType<DataContent>());
|
|
var text = Assert.Single(captured.OfType<TextContent>());
|
|
Assert.Contains("per-mount capture limit", text.Text);
|
|
Assert.Contains("/output/b.bin", text.Text);
|
|
}
|
|
finally
|
|
{
|
|
Directory.Delete(dir, recursive: true);
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void CaptureWrittenFiles_TotalLimit_OmitsAcrossMounts()
|
|
{
|
|
var dirA = Directory.CreateTempSubdirectory("fmh-totalA-").FullName;
|
|
var dirB = Directory.CreateTempSubdirectory("fmh-totalB-").FullName;
|
|
try
|
|
{
|
|
var mountA = FileMountHelper.Normalize(new FileMount(dirA, "/a", FileMountMode.ReadWrite));
|
|
var mountB = FileMountHelper.Normalize(new FileMount(dirB, "/b", FileMountMode.ReadWrite));
|
|
var mounts = new[] { mountA, mountB };
|
|
var pre = FileMountHelper.SnapshotWritableMounts(mounts);
|
|
|
|
File.WriteAllBytes(Path.Combine(dirA, "a.bin"), new byte[500]);
|
|
File.WriteAllBytes(Path.Combine(dirB, "b.bin"), new byte[500]);
|
|
|
|
// Total capture limit set so the first file fits and the second triggers
|
|
// the cross-mount total cap.
|
|
var limits = new ProcessExecutionLimits { MaxTotalCapturedFileBytes = 600 };
|
|
var captured = FileMountHelper.CaptureWrittenFiles(mounts, pre, limits);
|
|
|
|
Assert.Single(captured.OfType<DataContent>());
|
|
var text = Assert.Single(captured.OfType<TextContent>());
|
|
Assert.Contains("total capture limit", text.Text);
|
|
}
|
|
finally
|
|
{
|
|
Directory.Delete(dirA, recursive: true);
|
|
Directory.Delete(dirB, recursive: true);
|
|
}
|
|
}
|
|
}
|