refactor: 枚举移入Models目录,命名空间更新为Rainbow.Entity.Models
大石头 authored at 2026-07-02 12:54:58
3.32 KiB
RainbowBridge
using Rainbow.Services;
using Xunit;

namespace XUnitTest.Rainbow.Services;

public class ShellExecutorTests
{
    [Fact(DisplayName = "ShellExecutor_构造_默认超时30秒")]
    public void Constructor_DefaultTimeout()
    {
        var executor = new ShellExecutor();
        Assert.Equal(30_000, executor.TimeoutMs);
        Assert.True(executor.EnableAudit);
    }

    [Fact(DisplayName = "ShellExecutor_Execute_Null命令抛异常")]
    public void Execute_NullCommand_Throws()
    {
        var executor = new ShellExecutor();
        Assert.Throws<ArgumentNullException>(() => executor.Execute(null!, ""));
    }

    [Fact(DisplayName = "ShellExecutor_Execute_空命令抛异常")]
    public void Execute_EmptyCommand_Throws()
    {
        var executor = new ShellExecutor();
        Assert.Throws<ArgumentNullException>(() => executor.Execute("", ""));
    }

    [Fact(DisplayName = "ShellExecutor_Execute_Windows执行echo返回结果")]
    public void Execute_Simulated_ReturnsResult()
    {
        var executor = new ShellExecutor();
        var result = executor.Execute("echo", "hello");

        Assert.NotNull(result);
        Assert.Equal(0, result.ExitCode);
        // 跨平台重构后,Windows 用 cmd.exe /c 真实执行,不再返回"[模拟]"
        Assert.Contains("hello", result.Stdout);
        Assert.True(result.Success);
    }

    [Fact(DisplayName = "ShellExecutor_Execute_Sudo不在白名单返回Fail")]
    public void Execute_SudoNotInWhitelist_ReturnsFail()
    {
        var whitelist = new SudoWhitelist("/sbin/ip");
        var executor = new ShellExecutor(whitelist);

        var result = executor.Execute("/bin/rm", "-rf /", needSudo: true);

        Assert.NotNull(result);
        Assert.Equal(-1, result.ExitCode);
        Assert.False(result.Success);
        Assert.Contains("不在白名单", result.Stderr);
    }

    [Fact(DisplayName = "ShellExecutor_Execute_Sudo在白名单不抛异常")]
    public void Execute_SudoInWhitelist_Allowed()
    {
        var whitelist = new SudoWhitelist("/sbin/ip");
        var executor = new ShellExecutor(whitelist);

        // 跨平台重构后,sudo 白名单检查通过,但 Windows 上无 sudo 命令
        // 实际执行可能失败(ExitCode != 0),但只要不因白名单拒绝即可
        var result = executor.Execute("/sbin/ip", "addr", needSudo: true);

        Assert.NotNull(result);
        // 检查未被白名单拒绝(stderr 不含"不在白名单")
        Assert.DoesNotContain("不在白名单", result.Stderr ?? "");
    }

    [Fact(DisplayName = "ShellExecutor_ExecuteAsync_跨平台执行echo返回成功")]
    public async Task ExecuteAsync_Simulated_ReturnsResult()
    {
        var executor = new ShellExecutor();
        var result = await executor.ExecuteAsync("echo", "test");

        Assert.NotNull(result);
        Assert.Equal(0, result.ExitCode);
        Assert.True(result.Success);
    }

    [Fact(DisplayName = "ShellExecutor_ExecuteAsync_Windows命令正确执行")]
    public async Task ExecuteAsync_StringArguments_Correct()
    {
        var executor = new ShellExecutor();
        // 跨平台:Windows 用 cmd.exe /c,echo 是内置命令可正常执行
        var result = await executor.ExecuteAsync("echo", "hello world");

        Assert.NotNull(result);
        Assert.Contains("hello world", result.Stdout);
    }
}