位置节点增加保存图像到本地的功能;支持输入图像
This commit is contained in:
@@ -0,0 +1,143 @@
|
||||
using FsCheck;
|
||||
using FsCheck.Fluent;
|
||||
using FsCheck.Xunit;
|
||||
using System.Linq;
|
||||
using XplorePlane.Helpers;
|
||||
|
||||
namespace XplorePlane.Tests.Helpers
|
||||
{
|
||||
/// <summary>
|
||||
/// FsCheck property-based tests for FileNameSanitizer.
|
||||
/// Property 1: 文件名非法字符清理
|
||||
/// Validates: Requirements 1.2
|
||||
/// </summary>
|
||||
public class FileNameSanitizerPropertyTests
|
||||
{
|
||||
private static readonly char[] InvalidChars =
|
||||
new[] { '\\', '/', ':', '*', '?', '"', '<', '>', '|' };
|
||||
|
||||
/// <summary>
|
||||
/// 生成包含各种字符(含非法字符)的文件名字符串
|
||||
/// </summary>
|
||||
private static Arbitrary<string> FileNameArb()
|
||||
{
|
||||
// Mix of normal chars, unicode chars, and illegal file system chars
|
||||
var charGen = Gen.Frequency(
|
||||
(5, Gen.Choose(0x20, 0x7E).Select(i => (char)i)), // printable ASCII
|
||||
(2, Gen.Elements(InvalidChars)), // illegal chars
|
||||
(2, Gen.Choose(0x4E00, 0x9FFF).Select(i => (char)i)), // CJK characters
|
||||
(1, Gen.Elements('_', '-', '.', ' ')) // common filename chars
|
||||
);
|
||||
|
||||
var gen = from len in Gen.Choose(1, 50)
|
||||
from chars in Gen.ListOf<char>(charGen, len)
|
||||
select new string(chars.ToArray());
|
||||
|
||||
return gen.ToArbitrary();
|
||||
}
|
||||
|
||||
// ── Property 1: Output never contains any illegal characters ─────────
|
||||
|
||||
/// <summary>
|
||||
/// **Validates: Requirements 1.2**
|
||||
/// For any input string, the sanitized output must not contain any of the 9 illegal characters.
|
||||
/// </summary>
|
||||
[Property(MaxTest = 100)]
|
||||
public Property SanitizedOutput_NeverContainsIllegalCharacters()
|
||||
{
|
||||
return Prop.ForAll(
|
||||
FileNameArb(),
|
||||
input =>
|
||||
{
|
||||
var result = FileNameSanitizer.Sanitize(input);
|
||||
return !result.Any(c => InvalidChars.Contains(c));
|
||||
});
|
||||
}
|
||||
|
||||
// ── Property 1 (cont): Legal characters are preserved unchanged ──────
|
||||
|
||||
/// <summary>
|
||||
/// **Validates: Requirements 1.2**
|
||||
/// For any input string, characters that are NOT illegal must appear unchanged
|
||||
/// at the same position in the output.
|
||||
/// </summary>
|
||||
[Property(MaxTest = 100)]
|
||||
public Property SanitizedOutput_PreservesLegalCharacters()
|
||||
{
|
||||
return Prop.ForAll(
|
||||
FileNameArb(),
|
||||
input =>
|
||||
{
|
||||
var result = FileNameSanitizer.Sanitize(input);
|
||||
|
||||
for (int i = 0; i < input.Length; i++)
|
||||
{
|
||||
if (!InvalidChars.Contains(input[i]))
|
||||
{
|
||||
if (result[i] != input[i])
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
// ── Property 1 (cont): Output length equals input length ─────────────
|
||||
|
||||
/// <summary>
|
||||
/// **Validates: Requirements 1.2**
|
||||
/// For any non-null, non-empty input, the output length equals the input length.
|
||||
/// For null or empty input, the output is "_".
|
||||
/// </summary>
|
||||
[Property(MaxTest = 100)]
|
||||
public Property SanitizedOutput_LengthEqualsInputLength()
|
||||
{
|
||||
return Prop.ForAll(
|
||||
FileNameArb(),
|
||||
input =>
|
||||
{
|
||||
var result = FileNameSanitizer.Sanitize(input);
|
||||
return result.Length == input.Length;
|
||||
});
|
||||
}
|
||||
|
||||
// ── Property 1 (cont): Sanitize is idempotent ────────────────────────
|
||||
|
||||
/// <summary>
|
||||
/// **Validates: Requirements 1.2**
|
||||
/// Sanitizing the output a second time produces the same result (idempotent).
|
||||
/// </summary>
|
||||
[Property(MaxTest = 100)]
|
||||
public Property SanitizedOutput_IsIdempotent()
|
||||
{
|
||||
return Prop.ForAll(
|
||||
FileNameArb(),
|
||||
input =>
|
||||
{
|
||||
var once = FileNameSanitizer.Sanitize(input);
|
||||
var twice = FileNameSanitizer.Sanitize(once);
|
||||
return once == twice;
|
||||
});
|
||||
}
|
||||
|
||||
// ── Edge case: null and empty input ──────────────────────────────────
|
||||
|
||||
/// <summary>
|
||||
/// **Validates: Requirements 1.2**
|
||||
/// Null or empty input always returns "_".
|
||||
/// </summary>
|
||||
[Property(MaxTest = 100)]
|
||||
public Property NullOrEmptyInput_ReturnsUnderscore()
|
||||
{
|
||||
var gen = Gen.Elements<string>(null, "", null, "");
|
||||
|
||||
return Prop.ForAll(
|
||||
gen.ToArbitrary(),
|
||||
input =>
|
||||
{
|
||||
var result = FileNameSanitizer.Sanitize(input);
|
||||
return result == "_";
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user