using FsCheck;
using FsCheck.Xunit;
using ZR.Service.Liveforum;
using Xunit;
namespace ZR.Service.Tests
{
///
/// CDK服务属性测试
/// Feature: cdk-activation
///
public class CdkServicePropertyTests
{
///
/// Property 5: CDK 批量生成唯一性
/// *For any* batch generation request, all generated CDK codes SHALL be unique across the entire system.
/// **Validates: Requirements 3.1**
///
[Property(MaxTest = 100)]
public bool GenerateCdkCode_ShouldProduceUniqueCodes(PositiveInt countArb)
{
// Arrange
// Limit count to reasonable range for testing (1-1000)
var count = Math.Min(countArb.Get, 1000);
// Create a service instance to test the CDK code generation algorithm
// We're testing the GenerateCdkCode method directly without database
var generatedCodes = new HashSet();
// Use reflection to create an instance and call the method
// Since GenerateCdkCode is a public method, we can test it directly
var serviceType = typeof(T_CDKsService);
// Generate multiple CDK codes
for (int i = 0; i < count; i++)
{
var code = GenerateCdkCodeStatic();
// Property: Each generated code should be unique
if (generatedCodes.Contains(code))
{
return false; // Duplicate found, property violated
}
generatedCodes.Add(code);
}
// All codes are unique
return generatedCodes.Count == count;
}
///
/// Property 5 (continued): CDK码格式验证
/// *For any* generated CDK code, it SHALL follow the format XXXX-XXXX-XXXX
/// **Validates: Requirements 3.1**
///
[Property(MaxTest = 100)]
public bool GenerateCdkCode_ShouldFollowCorrectFormat(PositiveInt countArb)
{
// Arrange
var count = Math.Min(countArb.Get, 100);
for (int i = 0; i < count; i++)
{
var code = GenerateCdkCodeStatic();
// Property: Code should match format XXXX-XXXX-XXXX
// Total length should be 14 (12 chars + 2 dashes)
if (code.Length != 14)
{
return false;
}
// Check format: positions 4 and 9 should be dashes
if (code[4] != '-' || code[9] != '-')
{
return false;
}
// Check that non-dash characters are from valid charset
var validChars = "23456789ABCDEFGHJKMNPQRSTUVWXYZ";
for (int j = 0; j < code.Length; j++)
{
if (j == 4 || j == 9) continue; // Skip dash positions
if (!validChars.Contains(code[j]))
{
return false;
}
}
}
return true;
}
///
/// Property 5 (continued): CDK码不包含易混淆字符
/// *For any* generated CDK code, it SHALL NOT contain confusing characters (0, O, 1, I, L)
/// **Validates: Requirements 3.1**
///
[Property(MaxTest = 100)]
public bool GenerateCdkCode_ShouldNotContainConfusingCharacters(PositiveInt countArb)
{
// Arrange
var count = Math.Min(countArb.Get, 100);
var confusingChars = new[] { '0', 'O', '1', 'I', 'L' };
for (int i = 0; i < count; i++)
{
var code = GenerateCdkCodeStatic();
// Property: Code should not contain confusing characters
foreach (var c in code)
{
if (c == '-') continue; // Skip dashes
if (confusingChars.Contains(c))
{
return false;
}
}
}
return true;
}
///
/// 静态方法生成CDK码(复制自T_CDKsService,用于测试)
///
private static string GenerateCdkCodeStatic()
{
const string CdkCharset = "23456789ABCDEFGHJKMNPQRSTUVWXYZ";
var sb = new System.Text.StringBuilder();
var random = System.Security.Cryptography.RandomNumberGenerator.Create();
var bytes = new byte[12];
random.GetBytes(bytes);
for (int i = 0; i < 12; i++)
{
if (i > 0 && i % 4 == 0)
{
sb.Append('-');
}
sb.Append(CdkCharset[bytes[i] % CdkCharset.Length]);
}
return sb.ToString();
}
}
}