using Admin.NET.Plugin.AiDOP.DataPlatform;
using SqlSugar;
using Xunit;
namespace Admin.NET.Plugin.AiDOP.Tests.DataPlatform;
///
/// 九宫格取数与入站诊断日志的守卫。锚在实现正文,避免匹配到接口声明。
///
public class GridAndInboundGuardTests
{
private static string Read(string relative)
{
var path = Path.Combine(FindRepoRoot(), relative);
return File.ReadAllText(path);
}
[Fact]
public void Seed_Defines_S5_L1_004()
{
var source = Read(@"server\Plugins\Admin.NET.Plugin.AiDOP\Infrastructure\AidopKpiMasterSeed.cs");
Assert.Contains("\"S5_L1_004\"", source);
Assert.Contains("品类物料库存周转", source);
}
[Fact]
public void HomeGrid_ItemBizDate_DoesNotFallBackToModuleDate()
{
var source = Read(@"server\Plugins\Admin.NET.Plugin.AiDOP\Controllers\AidopKanbanController.Generic.cs");
Assert.Contains("v.biz_date AS BizDate", source);
Assert.Contains("filteredBundle == null ? v?.BizDate : null", source);
var items = source.IndexOf("items.Add(new", StringComparison.Ordinal);
Assert.True(items > 0);
var slice = source[items..source.IndexOf("return Ok", items, StringComparison.Ordinal)];
Assert.Contains("bizDate = itemBizDate", slice);
Assert.DoesNotContain("bizDate = bizDate", slice);
}
[Fact]
public void GateLog_SamplesBeforeConcat_AndDoesNotKillThePipeline()
{
var inventory = SliceMethod(Read(@"server\Plugins\Admin.NET.Plugin.AiDOP\MaterialWarehouse\InventoryMdpSyncService.cs"),
"private async Task LogWorkOrderNotFoundAsync");
Assert.Contains("LIMIT 20", inventory);
Assert.Contains("try", inventory);
Assert.DoesNotContain("GROUP_CONCAT(DISTINCT t.work_ord)", inventory);
Assert.Contains("LogWarning", inventory);
var shipFile = Read(@"server\Plugins\Admin.NET.Plugin.AiDOP\DataPlatform\Wms\ShipTransNeutralProjection.cs");
var mark = shipFile.IndexOf("写失败不得中断发运投影", StringComparison.Ordinal);
Assert.True(mark > 0);
var around = shipFile.Substring(Math.Max(0, mark - 120), 500);
Assert.Contains("try", around);
Assert.Contains("LIMIT 12", shipFile);
Assert.DoesNotContain("GROUP_CONCAT(DISTINCT CONCAT", shipFile);
Assert.Contains("LogWarning", shipFile);
}
[Fact]
public void ExtraParams_DropsConfigId_AndKeepsForeignKeys()
{
var dropped = new List();
var sqlServer = MdpSourceScopeFactory.SanitizeExtraParams(
"ConfigId=t8_v5;TrustServerCertificate=true;Application Name=aidop",
DbType.SqlServer, out dropped);
Assert.Contains("ConfigId", dropped, StringComparer.OrdinalIgnoreCase);
Assert.Contains("TrustServerCertificate", dropped, StringComparer.OrdinalIgnoreCase);
Assert.DoesNotContain("ConfigId", sqlServer ?? "", StringComparison.OrdinalIgnoreCase);
Assert.Contains("Application Name", sqlServer ?? "", StringComparison.OrdinalIgnoreCase);
var mysql = MdpSourceScopeFactory.SanitizeExtraParams(
"SslMode=Required;Connection Timeout=15",
DbType.MySql, out dropped);
Assert.Empty(dropped);
Assert.Contains("SslMode", mysql ?? "", StringComparison.OrdinalIgnoreCase);
var pg = MdpSourceScopeFactory.SanitizeExtraParams(
"SslMode=Require;Timeout=15",
DbType.PostgreSQL, out dropped);
Assert.Empty(dropped);
Assert.Contains("SslMode", pg ?? "", StringComparison.OrdinalIgnoreCase);
}
private static string SliceMethod(string source, string anchor)
{
var start = source.IndexOf(anchor, StringComparison.Ordinal);
Assert.True(start >= 0, anchor);
var end = source.IndexOf("\n private ", start + anchor.Length, StringComparison.Ordinal);
if (end < 0) end = source.IndexOf("\n public ", start + anchor.Length, StringComparison.Ordinal);
if (end < 0) end = source.Length;
return source[start..end];
}
private static string FindRepoRoot()
{
var dir = new DirectoryInfo(AppContext.BaseDirectory);
while (dir != null)
{
if (File.Exists(Path.Combine(dir.FullName, "AGENTS.md")))
return dir.FullName;
dir = dir.Parent;
}
throw new InvalidOperationException("找不到仓库根目录");
}
}