using System.Text.RegularExpressions;
using Xunit;
namespace Admin.NET.Plugin.AiDOP.Tests.DataPlatform;
///
/// 指标计算与诊断依据不得再出现 T8 列名或中文业务类型字面量。
/// T8 适配器文件不在扫描范围内。
///
public class NeutralLayerTokenGuardTests
{
private static readonly string[] Files =
[
Path.Combine("Supply", "S3MdpSyncTransformService.cs"),
Path.Combine("MaterialWarehouse", "S5MdpSyncTransformService.cs"),
Path.Combine("Manufacturing", "S6MdpSyncTransformService.cs"),
Path.Combine("FinishedWarehouse", "S7MdpSyncTransformService.cs"),
Path.Combine("SmartOps", "SmartDiagnosisEvidenceRegistry.cs"),
Path.Combine("SmartOps", "SmartOpsKpiAtomicBuildService.cs"),
Path.Combine("SmartOps", "S9CompositeKpiWriter.cs")
];
private static readonly string[] Tokens =
[
"mdp_std_t8_", "ztid", "lbs", "hzyn", "zfyn", "shyn", "shtime",
"noid", "rwnoid", "lynoid", "gdyn", "gdtime", "jhdate", "slzx", "zzzt",
"采购入库", "生产领料", "生产任务", "生产入库", "销售订单", "销售出库", "销售退货"
];
[Fact]
public void KpiReaders_DoNotContainT8Tokens()
{
var hits = new List();
foreach (var relative in Files)
{
var text = ReadPluginFile(relative);
foreach (var token in Tokens)
{
var pattern = token.Any(c => c > 127)
? Regex.Escape(token)
: $@"\b{Regex.Escape(token)}\b";
if (Regex.IsMatch(text, pattern))
hits.Add($"{relative}: {token}");
}
}
Assert.Empty(hits);
}
[Fact]
public void InventoryAndEmployeeKpiSql_FilterBySource()
{
var files = new[]
{
Path.Combine("Supply", "S3MdpSyncTransformService.cs"),
Path.Combine("MaterialWarehouse", "S5MdpSyncTransformService.cs"),
Path.Combine("Manufacturing", "S6MdpSyncTransformService.cs"),
Path.Combine("FinishedWarehouse", "S7MdpSyncTransformService.cs")
};
var hits = new List();
foreach (var relative in files)
{
var text = ReadPluginFile(relative);
foreach (Match match in Regex.Matches(text, @"from\s+mdp_std_(inv_trans|employee)\b", RegexOptions.IgnoreCase))
{
var window = text.Substring(match.Index, Math.Min(1200, text.Length - match.Index));
if (!window.Contains("source_system", StringComparison.OrdinalIgnoreCase))
hits.Add($"{relative}@{match.Index}");
}
}
Assert.Empty(hits);
}
private static string ReadPluginFile(string relative)
{
var dir = new DirectoryInfo(AppContext.BaseDirectory);
while (dir != null)
{
var candidate = Path.Combine(dir.FullName, "server", "Plugins", "Admin.NET.Plugin.AiDOP", relative);
if (File.Exists(candidate)) return File.ReadAllText(candidate);
dir = dir.Parent;
}
throw new FileNotFoundException(relative);
}
}