T8KpiTenantIsolationContractTests.cs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. using System.Text.RegularExpressions;
  2. using Xunit;
  3. namespace Admin.NET.Plugin.AiDOP.Tests.DataPlatform;
  4. public class T8KpiTenantIsolationContractTests
  5. {
  6. [Theory]
  7. [InlineData("MaterialWarehouse", "S5MdpSyncTransformService.cs", 6)]
  8. [InlineData("FinishedWarehouse", "S7MdpSyncTransformService.cs", 4)]
  9. public void StandardLayerQueries_FilterByTenantAndZtid(
  10. string moduleDirectory,
  11. string serviceFile,
  12. int expectedQueryCount)
  13. {
  14. var source = ReadServiceSource(moduleDirectory, serviceFile);
  15. var queries = ExtractStandardLayerQueries(source);
  16. Assert.Equal(expectedQueryCount, queries.Count);
  17. foreach (var query in queries)
  18. {
  19. Assert.Contains("@tenantId", query, StringComparison.OrdinalIgnoreCase);
  20. Assert.Contains("@ztid", query, StringComparison.OrdinalIgnoreCase);
  21. var aliases = Regex.Matches(
  22. query,
  23. @"(?:from|join)\s+mdp_std_t8_\w+\s+(?<alias>[a-z])\b",
  24. RegexOptions.IgnoreCase)
  25. .Select(match => match.Groups["alias"].Value)
  26. .Distinct(StringComparer.OrdinalIgnoreCase);
  27. foreach (var alias in aliases)
  28. {
  29. Assert.Matches(
  30. new Regex($@"\b{Regex.Escape(alias)}\.tenant_id\b", RegexOptions.IgnoreCase),
  31. query);
  32. }
  33. }
  34. Assert.Contains(
  35. "new SugarParameter(\"@tenantId\", option.TargetTenantId)",
  36. source,
  37. StringComparison.Ordinal);
  38. }
  39. [Fact]
  40. public void S5_FulfillmentAndEfficiency_KeepEveryJoinedTableInTargetTenant()
  41. {
  42. var source = ReadServiceSource("MaterialWarehouse", "S5MdpSyncTransformService.cs");
  43. Assert.Contains("l.tenant_id=h.tenant_id", source, StringComparison.OrdinalIgnoreCase);
  44. Assert.Contains("where tenant_id=@tenantId and ztid=@ztid", source, StringComparison.OrdinalIgnoreCase);
  45. Assert.Contains("h.tenant_id=@tenantId and h.ztid=@ztid", source, StringComparison.OrdinalIgnoreCase);
  46. Assert.Contains("b.tenant_id=a.tenant_id", source, StringComparison.OrdinalIgnoreCase);
  47. Assert.Contains("where tenant_id=@tenantId and ztid=@ztid and zzzt='在职'", source, StringComparison.OrdinalIgnoreCase);
  48. }
  49. [Fact]
  50. public void S7_CycleFulfillmentAndEfficiency_KeepEveryJoinedTableInTargetTenant()
  51. {
  52. var source = ReadServiceSource("FinishedWarehouse", "S7MdpSyncTransformService.cs");
  53. Assert.Contains("b.tenant_id=a.tenant_id", source, StringComparison.OrdinalIgnoreCase);
  54. Assert.Contains("d.tenant_id=a.tenant_id", source, StringComparison.OrdinalIgnoreCase);
  55. Assert.Contains("c.tenant_id=a.tenant_id", source, StringComparison.OrdinalIgnoreCase);
  56. Assert.Contains("a.tenant_id=@tenantId and a.ztid=@ztid", source, StringComparison.OrdinalIgnoreCase);
  57. Assert.Contains("where tenant_id=@tenantId and ztid=@ztid and zzzt='在职'", source, StringComparison.OrdinalIgnoreCase);
  58. }
  59. private static List<string> ExtractStandardLayerQueries(string source) =>
  60. Regex.Matches(
  61. source,
  62. @"const string \w+\s*=\s*@""(?<sql>[\s\S]*?)"";",
  63. RegexOptions.CultureInvariant)
  64. .Select(match => match.Groups["sql"].Value)
  65. .Where(sql => sql.Contains("mdp_std_t8_", StringComparison.OrdinalIgnoreCase))
  66. .ToList();
  67. private static string ReadServiceSource(string moduleDirectory, string serviceFile)
  68. {
  69. var dir = new DirectoryInfo(AppContext.BaseDirectory);
  70. while (dir != null)
  71. {
  72. var candidate = Path.Combine(
  73. dir.FullName,
  74. "server",
  75. "Plugins",
  76. "Admin.NET.Plugin.AiDOP",
  77. moduleDirectory,
  78. serviceFile);
  79. if (File.Exists(candidate)) return File.ReadAllText(candidate);
  80. dir = dir.Parent;
  81. }
  82. throw new FileNotFoundException(serviceFile);
  83. }
  84. }