chore: import upstream snapshot with attribution
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

This commit is contained in:
wehub-resource-sync
2026-07-13 13:39:25 +08:00
commit db620d33df
5151 changed files with 925932 additions and 0 deletions
@@ -0,0 +1,141 @@
// Copyright (c) Microsoft. All rights reserved.
using System;
namespace Microsoft.Agents.AI.Tools.Shell.UnitTests;
/// <summary>
/// Direct coverage for <see cref="ShellSession.TruncateHeadTail"/> (internal,
/// reachable via InternalsVisibleTo). The function is on the hot path for
/// every shell command — both LocalShellExecutor and DockerShellExecutor feed
/// captured stdout/stderr through it before returning.
/// </summary>
public sealed class ShellSessionTests
{
[Fact]
public void QuotePosix_NoSpecialChars_WrapsInSingleQuotes()
{
Assert.Equal("'/tmp/work'", ShellSession.QuotePosix("/tmp/work"));
}
[Fact]
public void QuotePosix_DollarBacktickAndCommandSubstitution_ProducesLiteralString()
{
// The whole point: these substrings must NOT be interpreted by sh.
Assert.Equal("'/tmp/$(touch /pwn)'", ShellSession.QuotePosix("/tmp/$(touch /pwn)"));
Assert.Equal("'/tmp/$VAR'", ShellSession.QuotePosix("/tmp/$VAR"));
Assert.Equal("'/tmp/`id`'", ShellSession.QuotePosix("/tmp/`id`"));
}
[Fact]
public void QuotePosix_EmbeddedSingleQuote_ClosesAndReopens()
{
// POSIX: single-quoted strings cannot contain a single quote, so we close,
// emit an escaped quote, and reopen: a' -> 'a'\''b' -> a'b literal.
Assert.Equal("'a'\\''b'", ShellSession.QuotePosix("a'b"));
}
[Fact]
public void QuotePowerShell_DollarAndSubexpression_ProducesLiteralString()
{
Assert.Equal("'C:\\$(throw)'", ShellSession.QuotePowerShell("C:\\$(throw)"));
Assert.Equal("'C:\\$env:PATH'", ShellSession.QuotePowerShell("C:\\$env:PATH"));
}
[Fact]
public void QuotePowerShell_EmbeddedSingleQuote_DoublesIt()
{
// PowerShell: 'a''b' is the literal string a'b.
Assert.Equal("'a''b'", ShellSession.QuotePowerShell("a'b"));
}
[Fact]
public void TruncateHeadTail_UnderCap_ReturnsInputUnchanged()
{
const string Input = "short";
var (text, truncated) = ShellSession.TruncateHeadTail(Input, cap: 1024);
Assert.Equal(Input, text);
Assert.False(truncated);
}
[Fact]
public void TruncateHeadTail_ExactlyAtCap_ReturnsInputUnchanged()
{
var input = new string('x', 100);
var (text, truncated) = ShellSession.TruncateHeadTail(input, cap: 100);
Assert.Equal(input, text);
Assert.False(truncated);
}
[Fact]
public void TruncateHeadTail_OverCap_TruncatesAndIncludesMarker()
{
var input = "HEAD" + new string('x', 1000) + "TAIL";
var (text, truncated) = ShellSession.TruncateHeadTail(input, cap: 20);
Assert.True(truncated);
Assert.Contains("[... truncated", text, StringComparison.Ordinal);
Assert.Contains("HEAD", text, StringComparison.Ordinal);
Assert.Contains("TAIL", text, StringComparison.Ordinal);
// Truncated output is roughly cap + marker chars; confirm it's much
// smaller than the input.
Assert.True(text.Length < input.Length);
}
[Fact]
public void TruncateHeadTail_EmptyString_ReturnsEmpty()
{
var (text, truncated) = ShellSession.TruncateHeadTail(string.Empty, cap: 10);
Assert.Equal(string.Empty, text);
Assert.False(truncated);
}
[Fact]
public void TruncateHeadTail_MultiByteUtf8_RespectsByteBudgetAndRuneBoundaries()
{
// Each "🔥" is 4 UTF-8 bytes (and 2 UTF-16 code units). 50 of them = 200 bytes.
var input = string.Concat(System.Linq.Enumerable.Repeat("🔥", 50));
Assert.Equal(200, System.Text.Encoding.UTF8.GetByteCount(input));
var (text, truncated) = ShellSession.TruncateHeadTail(input, cap: 40);
Assert.True(truncated);
// Result must round-trip through UTF-8 unchanged: no rune was split.
var roundTripped = System.Text.Encoding.UTF8.GetString(System.Text.Encoding.UTF8.GetBytes(text));
Assert.Equal(text, roundTripped);
// The retained head + tail content must not exceed the byte budget.
// (The marker line is appended on top of that budget, by design.)
var marker = text[text.IndexOf('\n', StringComparison.Ordinal)..text.LastIndexOf('\n')];
var preserved = text.Replace(marker, string.Empty, StringComparison.Ordinal).Replace("\n", string.Empty, StringComparison.Ordinal);
Assert.True(System.Text.Encoding.UTF8.GetByteCount(preserved) <= 40);
}
[Fact]
public void TruncateHeadTail_NonAsciiAtBoundary_DoesNotProduceReplacementChar()
{
// 4-byte UTF-8 emoji surrounded by ASCII; cap chosen so naive char-based
// truncation would have split a surrogate pair. The new implementation
// must skip the rune that doesn't fit instead of emitting U+FFFD.
const string Input = "AAAA🔥BBBBCCCC🔥DDDD";
var (text, _) = ShellSession.TruncateHeadTail(Input, cap: 8);
Assert.DoesNotContain("\uFFFD", text);
}
[Fact]
public void TruncateHeadTail_UnpairedHighSurrogate_DoesNotMisalignByteCount()
{
// An unpaired high surrogate (no following low surrogate) used to make the
// prefix walker advance by 2 chars and miscount bytes. Verify that the
// function completes, returns a sensible result, and respects the cap.
var input = "AAAA" + new string('\uD83D', 1) + "BBBB"; // lone high surrogate
var (text, _) = ShellSession.TruncateHeadTail(input, cap: 6);
// The encoder substitutes U+FFFD for the unpaired surrogate when emitting bytes,
// so we just check that the call did not overrun and produced a result that
// round-trips through UTF-8.
var rt = System.Text.Encoding.UTF8.GetString(System.Text.Encoding.UTF8.GetBytes(text));
Assert.Equal(text, rt);
}
}