| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293 |
- using Admin.NET.Plugin.AiDOP.Service.S8.Rules;
- using System.Text.Json;
- using Xunit;
- namespace Admin.NET.Test.S8;
- /// <summary>
- /// R2-TIMEOUT-EVALUATOR 纯逻辑回归。覆盖 params_json 解析 + dedup_key 生成稳定性。
- /// 不接 DB / 不接 DI;evaluator 的 SQL 与 SqlSugarRepository 路径走 run-once 端到端验证。
- /// </summary>
- public class S8TimeoutEvaluatorTests
- {
- [Fact]
- public void TimeoutParams_Parses_FullSpec()
- {
- var json = """
- {
- "dueAtField": "due_at",
- "statusField": "status",
- "completedStates": ["CLOSED", "DONE", "COMPLETED"],
- "objectCodeField": "related_object_code",
- "objectIdField": "source_object_id",
- "graceMinutes": 5,
- "exceptionTypeCode": "DELIVERY_DELAY"
- }
- """;
- var p = S8TimeoutParams.Parse(json);
- Assert.Equal("due_at", p.DueAtField);
- Assert.Equal("status", p.StatusField);
- Assert.Equal(new[] { "CLOSED", "DONE", "COMPLETED" }, p.CompletedStates);
- Assert.Equal("related_object_code", p.ObjectCodeField);
- Assert.Equal("source_object_id", p.ObjectIdField);
- Assert.Equal(5, p.GraceMinutes);
- Assert.Equal("DELIVERY_DELAY", p.ExceptionTypeCode);
- }
- [Fact]
- public void TimeoutParams_Tolerates_MissingOptionalFields()
- {
- var json = """{ "dueAtField": "due_at", "statusField": "status", "exceptionTypeCode": "PENDING_SHIPMENT" }""";
- var p = S8TimeoutParams.Parse(json);
- Assert.Equal("due_at", p.DueAtField);
- Assert.Equal("status", p.StatusField);
- Assert.Empty(p.CompletedStates);
- Assert.Null(p.ObjectCodeField);
- Assert.Null(p.ObjectIdField);
- Assert.Equal(0, p.GraceMinutes);
- Assert.Equal("PENDING_SHIPMENT", p.ExceptionTypeCode);
- }
- [Fact]
- public void TimeoutParams_Skips_BlankCompletedStates()
- {
- var json = """{ "completedStates": ["CLOSED", " ", "", "DONE"] }""";
- var p = S8TimeoutParams.Parse(json);
- Assert.Equal(new[] { "CLOSED", "DONE" }, p.CompletedStates);
- }
- [Fact]
- public void TimeoutParams_Throws_OnInvalidJson()
- {
- // evaluator 在 EvaluateAsync 内 try/catch 该异常并降级为空命中;本断言锁定异常类型契约。
- Assert.Throws<JsonException>(() => S8TimeoutParams.Parse("not-a-json"));
- }
- [Fact]
- public void BuildDedupKey_IsStable_SameInputsSameOutput()
- {
- var k1 = S8TimeoutRuleEvaluator.BuildDedupKey(1, 1, "G01_TEST_TIMEOUT", "ORDER", "ORDER-TIMEOUT-01");
- var k2 = S8TimeoutRuleEvaluator.BuildDedupKey(1, 1, "G01_TEST_TIMEOUT", "ORDER", "ORDER-TIMEOUT-01");
- Assert.Equal(k1, k2);
- Assert.Equal("T1:F1:RG01_TEST_TIMEOUT:ORDER:ORDER-TIMEOUT-01", k1);
- }
- [Fact]
- public void BuildDedupKey_Differentiates_OnTenantFactoryRuleObject()
- {
- var baseKey = S8TimeoutRuleEvaluator.BuildDedupKey(1, 1, "R", "ORDER", "ID");
- Assert.NotEqual(baseKey, S8TimeoutRuleEvaluator.BuildDedupKey(2, 1, "R", "ORDER", "ID"));
- Assert.NotEqual(baseKey, S8TimeoutRuleEvaluator.BuildDedupKey(1, 2, "R", "ORDER", "ID"));
- Assert.NotEqual(baseKey, S8TimeoutRuleEvaluator.BuildDedupKey(1, 1, "R2", "ORDER", "ID"));
- Assert.NotEqual(baseKey, S8TimeoutRuleEvaluator.BuildDedupKey(1, 1, "R", "TASK", "ID"));
- Assert.NotEqual(baseKey, S8TimeoutRuleEvaluator.BuildDedupKey(1, 1, "R", "ORDER", "ID2"));
- }
- [Fact]
- public void BuildDedupKey_Length_FitsVarchar128()
- {
- // 实体定义 dedup_key VARCHAR(128)。本断言锁定常规标识符不溢出列长度。
- var k = S8TimeoutRuleEvaluator.BuildDedupKey(9999999, 9999999, "VERY_LONG_RULE_CODE_FOR_PADDING_64____", "EXTREMELY_LONG_OBJECT_TYPE______", "EXTREMELY_LONG_OBJECT_ID________");
- Assert.True(k.Length <= 128, $"dedup_key length {k.Length} exceeds 128: {k}");
- }
- }
|