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(); } } }