package com.battery.business.runtime;
|
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
|
import java.io.InputStream;
|
import java.nio.charset.StandardCharsets;
|
import java.util.Set;
|
|
import org.junit.jupiter.api.Test;
|
|
/** Ticket03 最终数据库基线的结构契约。 */
|
class FinalDatabaseBaselineContractTest
|
{
|
private static final Set<String> REQUIRED_TABLES = Set.of(
|
"t_battery_group", "t_battery_group_field", "t_battery_group_relation_field",
|
"t_device_adapter", "t_detection_cabinet", "t_detection_channel", "t_collector",
|
"t_test", "t_test_battery", "t_test_channel_binding", "t_test_collector_channel",
|
"t_test_warning_threshold", "t_test_realtime_record", "t_test_step_record",
|
"t_test_cycle_record", "t_test_data_revision_action", "t_test_warning_exception");
|
|
private static final Set<String> RETIRED_TABLES = Set.of(
|
"t_test_field_snapshot", "t_test_battery_field", "t_test_plan_step", "t_test_audit",
|
"t_protocol_message", "t_test_reception_interval", "t_history_sync_cursor", "t_data_gap",
|
"t_channel_lease", "t_collector_channel_lease", "t_test_data_override",
|
"t_test_console_import_record");
|
|
@Test
|
void finalBaselineContainsOnlyTheAcceptedBusinessModel()
|
{
|
String sql = resource("db/migration-final/V2__final_business_baseline.sql");
|
String platformSql = resource("db/migration-final/V1__ruoyi_platform_baseline.sql");
|
for (String table : REQUIRED_TABLES)
|
{
|
assertTrue(sql.matches("(?s).*CREATE TABLE\\s+" + table + "\\s*\\(.*"),
|
"缺少最终业务表 " + table);
|
}
|
for (String table : RETIRED_TABLES)
|
{
|
assertFalse(sql.matches("(?s).*CREATE TABLE\\s+" + table + "\\s*\\(.*"),
|
"不应创建废止表 " + table);
|
}
|
assertFalse(sql.matches("(?is).*\\bFOREIGN\\s+KEY\\b.*"), "最终基线不得建立物理外键");
|
assertFalse(platformSql.matches("(?is).*\\bFOREIGN\\s+KEY\\b.*"), "平台基线不得建立物理外键");
|
assertFalse(platformSql.matches("(?is).*\\bINT\\s+NOT\\s+NULL\\s+AUTO_INCREMENT\\b.*"),
|
"最终基线自增主键统一使用 BIGINT");
|
assertTrue(sql.contains("test_battery_id BIGINT NOT NULL AUTO_INCREMENT"));
|
assertTrue(sql.contains("DATETIME(3)"));
|
assertTrue(sql.contains("before_content_json JSON NULL"));
|
assertTrue(sql.contains("source_identity VARCHAR(256) NOT NULL"));
|
assertTrue(sql.contains("adapter_timezone_id VARCHAR(64) NOT NULL"));
|
assertTrue(sql.contains("connection_status IN ('ONLINE', 'OFFLINE')"));
|
assertTrue(sql.contains("reception_status IN ('NOT_STARTED', 'RECEIVING', 'PAUSED', 'ENDED')"));
|
assertTrue(sql.contains("threshold_id BIGINT NOT NULL"));
|
assertTrue(sql.contains("open_dedupe_key VARCHAR(512) GENERATED ALWAYS AS"));
|
}
|
|
@Test
|
void flywayPointsAtTheFinalBaselineLocation()
|
{
|
String config = resource("application.yml");
|
assertTrue(config.contains("locations: classpath:db/migration-final"));
|
}
|
|
private static String resource(String path)
|
{
|
try (InputStream stream = FinalDatabaseBaselineContractTest.class.getClassLoader()
|
.getResourceAsStream(path))
|
{
|
if (stream == null)
|
{
|
throw new AssertionError("缺少资源 " + path);
|
}
|
return new String(stream.readAllBytes(), StandardCharsets.UTF_8);
|
}
|
catch (Exception exception)
|
{
|
throw new AssertionError("无法读取资源 " + path, exception);
|
}
|
}
|
}
|