using System.Reflection;
using Microsoft.AspNetCore.Mvc;
using Admin.NET.Plugin.AiDOP.Controllers.S8;
using Admin.NET.Plugin.AiDOP.Entity.S8;
using Admin.NET.Plugin.AiDOP.Service.S8;
using Admin.NET.Plugin.AiDOP.Service.S8.Rules.DataAccess;
using Xunit;
namespace Admin.NET.Plugin.AiDOP.Tests.S8;
///
/// S8-STANDARD-DATASET-HARD-CUTOVER-1:规则创建只认治理数据集。
///
/// 本文件锁的是「创建链路上再也没有 SQL / 物理数据源的位置」,
/// 与 互补:那边证明类型不存在,
/// 这边证明**残存的类型也不再提供入口**。
///
public class S8DatasetOnlyRuleCreationTests
{
private static readonly Assembly PluginAssembly = typeof(AdoS8WatchRule).Assembly;
// ============================================================
// T7 / T8:向导与数据源入口
// ============================================================
///
/// T7:向导后端不得再持有任何生成 SQL 的能力。
///
/// 这几个方法曾按 monitor_object.source_table + monitor_metric 字段映射拼 SELECT,
/// 是 S8 最后一处「自己造 SQL 去读别人的业务表」。逐名断言而非只看行为,
/// 是因为它们是 private —— 行为测试删掉一个分支就能变绿,名字还在就说明能力还在。
///
[Theory]
[InlineData("BuildExpression")]
[InlineData("ValidateSqlIdentifier")]
[InlineData("BuildSoftDeletePredicate")]
public void ConfigDraftService_HasNoSqlGenerationCapability(string methodName)
{
Assert.Null(typeof(S8ConfigDraftService).GetMethod(
methodName, BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public));
}
/// 向导服务不得再注入任何能提供物理数据源的依赖。
[Fact]
public void ConfigDraftService_HoldsNoDataSourceDependency()
{
var fieldTypes = typeof(S8ConfigDraftService)
.GetFields(BindingFlags.Instance | BindingFlags.NonPublic)
.Select(f => f.FieldType.FullName ?? f.FieldType.Name)
.ToArray();
Assert.DoesNotContain(fieldTypes, t => t.Contains("AdoS8DataSource", StringComparison.Ordinal));
Assert.DoesNotContain(fieldTypes, t => t.Contains("S8SqlSugarScopeFactory", StringComparison.Ordinal));
// 正向:必须持有数据集目录,否则无从校验用户选的 dataset_code。
Assert.Contains(fieldTypes, t => t.Contains("IS8DatasetCatalog", StringComparison.Ordinal));
}
/// T8:数据源 Controller / Service / Entity 三者都不存在。
[Theory]
[InlineData("Admin.NET.Plugin.AiDOP.Entity.S8.AdoS8DataSource")]
[InlineData("Admin.NET.Plugin.AiDOP.Service.S8.S8DataSourceService")]
[InlineData("Admin.NET.Plugin.AiDOP.Controllers.S8.AdoS8ConfigDataSourcesController")]
[InlineData("Admin.NET.Plugin.AiDOP.Service.S8.Rules.S8DataSourceRowLoader")]
[InlineData("Admin.NET.Plugin.AiDOP.Service.S8.Rules.S8SqlSugarScopeFactory")]
[InlineData("Admin.NET.Plugin.AiDOP.Service.S8.Rules.DataAccess.S8LegacySqlDataProvider")]
[InlineData("Admin.NET.Plugin.AiDOP.Service.S8.Rules.DataAccess.IS8LegacySqlDataProvider")]
[InlineData("Admin.NET.Plugin.AiDOP.Service.S8.Rules.DataAccess.S8DataAccessMode")]
[InlineData("Admin.NET.Plugin.AiDOP.Service.S8.Rules.DataAccess.S8RuleCreationPolicy")]
[InlineData("Admin.NET.Plugin.AiDOP.Service.S8.Rules.DataAccess.S8RuleCreationOrigin")]
public void LegacyDataAccessType_NoLongerExists(string fullName)
{
Assert.Null(PluginAssembly.GetType(fullName, throwOnError: false));
}
// ============================================================
// 数据集目录端点
// ============================================================
///
/// 取代数据源端点的是一个**只读**目录。二者性质不同,不是改名:
/// 旧的是租户可写的物理连接配置,新的是平台级只读目录。
/// 因此本用例断言它一个写动作都没有。
///
[Fact]
public void DatasetsController_IsReadOnly()
{
var actions = typeof(AdoS8ConfigDatasetsController)
.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)
.ToArray();
Assert.NotEmpty(actions);
foreach (var m in actions)
{
Assert.Empty(m.GetCustomAttributes());
Assert.Empty(m.GetCustomAttributes());
Assert.Empty(m.GetCustomAttributes());
Assert.Empty(m.GetCustomAttributes());
}
}
// ============================================================
// T11:Rule 01 仍然合法
// ============================================================
///
/// T11:Rule 01 的配置形态在删掉三个 Legacy 列之后仍然完整可表达 ——
/// 它本来就只依赖 dataset_code,这也是当初把它建成 STANDARD_DATASET 的意义。
///
[Fact]
public void Rule01Shape_RemainsExpressible_AfterLegacyColumnsRemoved()
{
var rule01 = new AdoS8WatchRule
{
Id = 1329909460023L,
RuleCode = "RULE_S4_PURCHASE_DELIVERY_DATE_DELAY",
TenantId = 838257186181189L,
FactoryId = 838257186320453L,
RuleType = "TIMEOUT",
DatasetCode = "PURCHASE_DELIVERY",
Enabled = false
};
Assert.Equal("PURCHASE_DELIVERY", rule01.DatasetCode);
Assert.False(rule01.Enabled);
// 保存级校验只看 dataset_code 是否在目录内 —— Rule 01 用的正是真实业务数据集定义。
var catalog = new S8DatasetCatalog(new IS8DatasetDefinitionSource[]
{
new Admin.NET.Plugin.AiDOP.Service.S8.Rules.DataAccess.Providers.S8BusinessDatasetDefinitions()
});
S8WatchRuleDataAccessValidator.ValidateForSave(rule01, catalog);
}
}