build-flow.api/tests/BuildFlow.File.Tests/SanitizeRulesTests.cs

148 lines
5.0 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using File.Application.Common;
using FluentAssertions;
using Xunit;
namespace BuildFlow.File.Tests;
/// <summary>
/// 输入清洗规则单测:这是文件服务的安全防线(路径遍历、桶名注入、目录穿越)。
/// 覆盖所有公开方法的合法/非法/边界场景。
/// </summary>
public class SanitizeRulesTests
{
// ===== IsValidBucketName =====
[Theory]
[InlineData("my-bucket")] // 标准合法
[InlineData("rag.files.2024")] // 含点和数字
[InlineData("abc")] // 最短 3 字符
[InlineData("a01234567890123456789012345678901234567890123456789012345678901")] // 最长 63 字符
public void IsValidBucketName_合法桶名_返回true(string name)
{
SanitizeRules.IsValidBucketName(name).Should().BeTrue();
}
[Theory]
[InlineData(null)] // null
[InlineData("")] // 空串
[InlineData("ab")] // 太短 <3
[InlineData("A-Bucket")] // 含大写
[InlineData("-leading")] // 以 - 开头
[InlineData("trailing-")] // 以 - 结尾
[InlineData(".dot-first")] // 以 . 开头
[InlineData("under_score")] // 含下划线(非法)
[InlineData("中文桶名")] // 含非 ASCII
[InlineData("has space")] // 含空格
[InlineData("a01234567890123456789012345678901234567890123456789012345678901234")] // 太长 >63
public void IsValidBucketName_非法桶名_返回false(string? name)
{
SanitizeRules.IsValidBucketName(name).Should().BeFalse();
}
// ===== IsValidObjectKey(路径遍历防护 - 安全关键)=====
[Theory]
[InlineData("documents/report.pdf")]
[InlineData("uuid-550e8400-e29b-41d4-a716-446655440000")]
[InlineData("a")] // 单字符
[InlineData("folder/sub/deep/file.txt")] // 多级
public void IsValidObjectKey_合法key_返回true(string key)
{
SanitizeRules.IsValidObjectKey(key).Should().BeTrue();
}
[Theory]
[InlineData("../etc/passwd")] // 路径遍历(最危险)
[InlineData("folder/../escape")] // 中间遍历
[InlineData("a../../b")] // 多重遍历
[InlineData("/leading-slash")] // 首斜杠(绝对路径注入)
[InlineData("double//slash")] // 双斜杠(目录穿越)
[InlineData("back\\slash")] // 反斜杠
[InlineData("control\tchar")] // 制表符
[InlineData("control\nchar")] // 换行符
[InlineData(null)]
[InlineData("")]
public void IsValidObjectKey_非法key_返回false(string? key)
{
SanitizeRules.IsValidObjectKey(key).Should().BeFalse();
}
[Fact]
public void IsValidObjectKey_超长key_返回false()
{
// 1025 字符,超出上限
var tooLong = new string('a', 1025);
SanitizeRules.IsValidObjectKey(tooLong).Should().BeFalse();
}
[Fact]
public void IsValidObjectKey_刚好1024字符_返回true()
{
// 边界值:1024 字符应合法
var maxLength = new string('a', 1024);
SanitizeRules.IsValidObjectKey(maxLength).Should().BeTrue();
}
// ===== IsValidFolderName =====
[Theory]
[InlineData("我的文件夹")] // 中文
[InlineData("Project 2024")]
[InlineData(" 需要trim的名称 ")] // 带空格(应 trim 后合法)
[InlineData("a")] // 单字符
public void IsValidFolderName_合法名_返回true(string name)
{
SanitizeRules.IsValidFolderName(name).Should().BeTrue();
}
[Theory]
[InlineData(null)]
[InlineData("")]
[InlineData(" ")] // 纯空白
[InlineData("has/slash")]
[InlineData("has\\backslash")]
[InlineData("tab\tinside")]
public void IsValidFolderName_非法名_返回false(string? name)
{
SanitizeRules.IsValidFolderName(name).Should().BeFalse();
}
// ===== IsValidResourceType =====
[Theory]
[InlineData("folder")]
[InlineData("file")]
[InlineData("FOLDER")] // 大小写不敏感
[InlineData("File")]
public void IsValidResourceType_合法_返回true(string t)
{
SanitizeRules.IsValidResourceType(t).Should().BeTrue();
}
[Theory]
[InlineData(null)]
[InlineData("")]
[InlineData("bucket")] // 非法类型
[InlineData("object")]
public void IsValidResourceType_非法_返回false(string? t)
{
SanitizeRules.IsValidResourceType(t).Should().BeFalse();
}
// ===== SanitizeFilename =====
[Fact]
public void SanitizeFilename_转义双引号()
{
SanitizeRules.SanitizeFilename("report\"final.pdf")
.Should().Be("report\\\"final.pdf");
}
[Fact]
public void SanitizeFilename_无双引号_原样返回()
{
SanitizeRules.SanitizeFilename("normal-name.txt")
.Should().Be("normal-name.txt");
}
}