148 lines
5.0 KiB
C#
148 lines
5.0 KiB
C#
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");
|
||
}
|
||
}
|