HaniBlindBox/server/HoneyBox/tests/HoneyBox.Tests/Services/UploadServicePropertyTests.cs
2026-01-19 15:05:52 +08:00

209 lines
7.7 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 FsCheck;
using FsCheck.Xunit;
using HoneyBox.Admin.Business.Services;
using Xunit;
namespace HoneyBox.Tests.Services;
/// <summary>
/// UploadService 属性测试
/// **Validates: Requirements 1.2, 1.3, 1.4, 1.5**
/// </summary>
public class UploadServicePropertyTests
{
/// <summary>
/// 允许的图片扩展名
/// </summary>
private static readonly string[] AllowedExtensions = { ".jpg", ".jpeg", ".png", ".gif", ".webp" };
/// <summary>
/// 不允许的扩展名示例
/// </summary>
private static readonly string[] DisallowedExtensions = { ".txt", ".pdf", ".exe", ".doc", ".html", ".js", ".css", ".zip", ".rar", ".mp4" };
#region Property 1:
/// <summary>
/// **Feature: image-upload-feature, Property 1: 文件格式验证**
/// *For any* 上传的文件,如果文件扩展名不在允许列表(jpg, jpeg, png, gif, webp)中,
/// THE Upload_Service SHALL 返回格式错误。
/// **Validates: Requirements 1.2, 1.4**
/// </summary>
[Property(MaxTest = 100)]
public bool InvalidExtension_ShouldBeRejected(PositiveInt seed)
{
// 从不允许的扩展名中选择一个
var extension = DisallowedExtensions[seed.Get % DisallowedExtensions.Length];
// 验证该扩展名被拒绝
return !UploadService.IsValidExtension(extension);
}
/// <summary>
/// **Feature: image-upload-feature, Property 1: 文件格式验证**
/// *For any* 允许的图片扩展名THE Upload_Service SHALL 接受该格式。
/// **Validates: Requirements 1.4**
/// </summary>
[Property(MaxTest = 100)]
public bool ValidExtension_ShouldBeAccepted(PositiveInt seed)
{
// 从允许的扩展名中选择一个
var extension = AllowedExtensions[seed.Get % AllowedExtensions.Length];
// 验证该扩展名被接受
return UploadService.IsValidExtension(extension);
}
/// <summary>
/// **Feature: image-upload-feature, Property 1: 文件格式验证**
/// *For any* 允许的图片扩展名大写形式THE Upload_Service SHALL 接受该格式(大小写不敏感)。
/// **Validates: Requirements 1.4**
/// </summary>
[Property(MaxTest = 100)]
public bool ValidExtension_CaseInsensitive_ShouldBeAccepted(PositiveInt seed)
{
// 从允许的扩展名中选择一个并转为大写
var extension = AllowedExtensions[seed.Get % AllowedExtensions.Length].ToUpperInvariant();
// 验证大写扩展名也被接受
return UploadService.IsValidExtension(extension);
}
#endregion
#region Property 2:
/// <summary>
/// **Feature: image-upload-feature, Property 2: 文件大小验证**
/// *For any* 上传的文件如果文件大小超过10MBTHE Upload_Service SHALL 返回大小超限错误。
/// **Validates: Requirements 1.3**
/// </summary>
[Property(MaxTest = 100)]
public bool FileSizeExceeding10MB_ShouldBeRejected(PositiveInt extraBytes)
{
// 10MB + 额外字节
var maxSize = 10L * 1024 * 1024;
var fileSize = maxSize + extraBytes.Get;
// 验证超过10MB的文件被拒绝
return !UploadService.IsValidFileSize(fileSize);
}
/// <summary>
/// **Feature: image-upload-feature, Property 2: 文件大小验证**
/// *For any* 文件大小在1字节到10MB之间THE Upload_Service SHALL 接受该文件。
/// **Validates: Requirements 1.3**
/// </summary>
[Property(MaxTest = 100)]
public bool FileSizeWithin10MB_ShouldBeAccepted(PositiveInt seed)
{
// 生成1字节到10MB之间的文件大小
var maxSize = 10L * 1024 * 1024;
var fileSize = (seed.Get % maxSize) + 1; // 确保至少1字节
// 验证在范围内的文件被接受
return UploadService.IsValidFileSize(fileSize);
}
/// <summary>
/// **Feature: image-upload-feature, Property 2: 文件大小验证**
/// *For any* 文件大小为0或负数THE Upload_Service SHALL 拒绝该文件。
/// **Validates: Requirements 1.3**
/// </summary>
[Property(MaxTest = 100)]
public bool ZeroOrNegativeFileSize_ShouldBeRejected(NegativeInt negativeSize)
{
// 验证0和负数被拒绝
return !UploadService.IsValidFileSize(0) && !UploadService.IsValidFileSize(negativeSize.Get);
}
#endregion
#region Property 3:
/// <summary>
/// **Feature: image-upload-feature, Property 3: 文件名唯一性**
/// *For any* 两次上传操作,即使上传相同的文件,生成的文件名 SHALL 不同。
/// **Validates: Requirements 1.5**
/// </summary>
[Property(MaxTest = 100)]
public bool GeneratedFileNames_ShouldBeUnique(PositiveInt seed)
{
// 使用相同的原始文件名
var extension = AllowedExtensions[seed.Get % AllowedExtensions.Length];
var originalFileName = $"test_file{extension}";
// 生成两个唯一文件名
var name1 = UploadService.GenerateUniqueFileName(originalFileName);
var name2 = UploadService.GenerateUniqueFileName(originalFileName);
// 验证两个文件名不同
return name1 != name2;
}
/// <summary>
/// **Feature: image-upload-feature, Property 3: 文件名唯一性**
/// *For any* 原始文件名,生成的唯一文件名 SHALL 保留原始扩展名。
/// **Validates: Requirements 1.5**
/// </summary>
[Property(MaxTest = 100)]
public bool GeneratedFileName_ShouldPreserveExtension(PositiveInt seed)
{
// 选择一个扩展名
var extension = AllowedExtensions[seed.Get % AllowedExtensions.Length];
var originalFileName = $"original_file_{seed.Get}{extension}";
// 生成唯一文件名
var uniqueName = UploadService.GenerateUniqueFileName(originalFileName);
// 验证扩展名被保留(转为小写)
return uniqueName.EndsWith(extension.ToLowerInvariant());
}
/// <summary>
/// **Feature: image-upload-feature, Property 3: 文件名唯一性**
/// *For any* 大写扩展名的文件,生成的唯一文件名 SHALL 将扩展名转为小写。
/// **Validates: Requirements 1.5**
/// </summary>
[Property(MaxTest = 100)]
public bool GeneratedFileName_ShouldNormalizeExtensionToLowercase(PositiveInt seed)
{
// 选择一个扩展名并转为大写
var extension = AllowedExtensions[seed.Get % AllowedExtensions.Length].ToUpperInvariant();
var originalFileName = $"FILE_{seed.Get}{extension}";
// 生成唯一文件名
var uniqueName = UploadService.GenerateUniqueFileName(originalFileName);
// 验证扩展名被转为小写
return uniqueName.EndsWith(extension.ToLowerInvariant());
}
/// <summary>
/// **Feature: image-upload-feature, Property 3: 文件名唯一性**
/// *For any* 多次生成的文件名,所有文件名 SHALL 互不相同。
/// **Validates: Requirements 1.5**
/// </summary>
[Property(MaxTest = 50)]
public bool MultipleGeneratedFileNames_ShouldAllBeUnique(PositiveInt seed)
{
var originalFileName = "test.jpg";
var generatedNames = new HashSet<string>();
// 生成多个文件名
var count = (seed.Get % 10) + 5; // 5-14个文件名
for (var i = 0; i < count; i++)
{
var name = UploadService.GenerateUniqueFileName(originalFileName);
if (!generatedNames.Add(name))
{
return false; // 发现重复
}
}
return true;
}
#endregion
}