NeutralLayerTokenGuardTests.cs 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. using System.Text.RegularExpressions;
  2. using Xunit;
  3. namespace Admin.NET.Plugin.AiDOP.Tests.DataPlatform;
  4. /// <summary>
  5. /// 指标计算与诊断依据不得再出现 T8 列名或中文业务类型字面量。
  6. /// T8 适配器文件不在扫描范围内。
  7. /// </summary>
  8. public class NeutralLayerTokenGuardTests
  9. {
  10. private static readonly string[] Files =
  11. [
  12. Path.Combine("Supply", "S3MdpSyncTransformService.cs"),
  13. Path.Combine("MaterialWarehouse", "S5MdpSyncTransformService.cs"),
  14. Path.Combine("Manufacturing", "S6MdpSyncTransformService.cs"),
  15. Path.Combine("FinishedWarehouse", "S7MdpSyncTransformService.cs"),
  16. Path.Combine("SmartOps", "SmartDiagnosisEvidenceRegistry.cs"),
  17. Path.Combine("SmartOps", "SmartOpsKpiAtomicBuildService.cs"),
  18. Path.Combine("SmartOps", "S9CompositeKpiWriter.cs")
  19. ];
  20. private static readonly string[] Tokens =
  21. [
  22. "mdp_std_t8_", "ztid", "lbs", "hzyn", "zfyn", "shyn", "shtime",
  23. "noid", "rwnoid", "lynoid", "gdyn", "gdtime", "jhdate", "slzx", "zzzt",
  24. "采购入库", "生产领料", "生产任务", "生产入库", "销售订单", "销售出库", "销售退货"
  25. ];
  26. [Fact]
  27. public void KpiReaders_DoNotContainT8Tokens()
  28. {
  29. var hits = new List<string>();
  30. foreach (var relative in Files)
  31. {
  32. var text = ReadPluginFile(relative);
  33. foreach (var token in Tokens)
  34. {
  35. var pattern = token.Any(c => c > 127)
  36. ? Regex.Escape(token)
  37. : $@"\b{Regex.Escape(token)}\b";
  38. if (Regex.IsMatch(text, pattern))
  39. hits.Add($"{relative}: {token}");
  40. }
  41. }
  42. Assert.Empty(hits);
  43. }
  44. [Fact]
  45. public void InventoryAndEmployeeKpiSql_FilterBySource()
  46. {
  47. var files = new[]
  48. {
  49. Path.Combine("Supply", "S3MdpSyncTransformService.cs"),
  50. Path.Combine("MaterialWarehouse", "S5MdpSyncTransformService.cs"),
  51. Path.Combine("Manufacturing", "S6MdpSyncTransformService.cs"),
  52. Path.Combine("FinishedWarehouse", "S7MdpSyncTransformService.cs")
  53. };
  54. var hits = new List<string>();
  55. foreach (var relative in files)
  56. {
  57. var text = ReadPluginFile(relative);
  58. foreach (Match match in Regex.Matches(text, @"from\s+mdp_std_(inv_trans|employee)\b", RegexOptions.IgnoreCase))
  59. {
  60. var window = text.Substring(match.Index, Math.Min(1200, text.Length - match.Index));
  61. if (!window.Contains("source_system", StringComparison.OrdinalIgnoreCase))
  62. hits.Add($"{relative}@{match.Index}");
  63. }
  64. }
  65. Assert.Empty(hits);
  66. }
  67. private static string ReadPluginFile(string relative)
  68. {
  69. var dir = new DirectoryInfo(AppContext.BaseDirectory);
  70. while (dir != null)
  71. {
  72. var candidate = Path.Combine(dir.FullName, "server", "Plugins", "Admin.NET.Plugin.AiDOP", relative);
  73. if (File.Exists(candidate)) return File.ReadAllText(candidate);
  74. dir = dir.Parent;
  75. }
  76. throw new FileNotFoundException(relative);
  77. }
  78. }