feat(ft546): persist shadow comparison evidence

This commit is contained in:
zgw
2026-08-14 17:25:52 +08:00
parent 6864010832
commit 240f5b0808
33 changed files with 3228 additions and 26 deletions

View File

@@ -1,6 +1,10 @@
package com.ruoyi.shadow;
import com.ruoyi.project.shadowtest.ForbiddenFactoryBean;
import com.ruoyi.shadow.evidence.ShadowCycleEvidenceCollector;
import com.ruoyi.shadow.evidence.ShadowEvidenceRepository;
import com.ruoyi.shadow.evidence.ShadowEvidenceStorageHealth;
import com.ruoyi.shadow.evidence.ShadowRunEvidence;
import com.ruoyi.shadow.startup.ShadowDatabaseGate;
import com.ruoyi.shadow.startup.ShadowStartupReport;
import com.ruoyi.shadow.web.ShadowStatusController;
@@ -23,6 +27,9 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
@@ -34,6 +41,11 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
class Ft546ShadowApplicationTest {
private static final String ARTIFACT_SHA256 =
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
private static final String CONFIGURATION_SHA256 =
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
private final WebApplicationContextRunner contextRunner =
new WebApplicationContextRunner()
.withInitializer(
@@ -74,6 +86,29 @@ class Ft546ShadowApplicationTest {
assertNotNull(context.getBean(RecordingFt546CommandGateway.class));
assertNotNull(context.getBean(
JdbcShadowTrafficStateRepository.class));
assertNotNull(context.getBean(ShadowRunEvidence.class));
assertNotNull(context.getBean(ShadowEvidenceRepository.class));
assertNotNull(context.getBean(ShadowEvidenceStorageHealth.class));
assertNotNull(context.getBean(ShadowCycleEvidenceCollector.class));
Set<String> cycleDependencies = Stream.of(context.getBeanFactory()
.getDependenciesForBean("ft546ShadowCycle"))
.collect(Collectors.toSet());
assertTrue(cycleDependencies.contains("shadowEvidenceRepository"));
assertTrue(cycleDependencies.contains(
"shadowEvidenceStorageHealth"));
assertTrue(cycleDependencies.contains(
"shadowCycleEvidenceCollector"));
assertTrue(cycleDependencies.contains("shadowStartupReport"));
Set<String> trafficDependencies = Stream.of(
context.getBeanFactory().getDependenciesForBean(
"shadowTrafficStateRepository"))
.collect(Collectors.toSet());
Set<String> evidenceDependencies = Stream.of(
context.getBeanFactory().getDependenciesForBean(
"shadowEvidenceRepository"))
.collect(Collectors.toSet());
assertTrue(trafficDependencies.contains("shadowEvidenceTx"));
assertTrue(evidenceDependencies.contains("shadowEvidenceTx"));
assertEquals(context.getBean(
JdbcShadowTrafficStateRepository.class),
context.getBean(com.ruoyi.wcs.port.out
@@ -141,13 +176,25 @@ class Ft546ShadowApplicationTest {
assertStartupFailure(configured(contextRunner).withPropertyValues(
"shadow.evidence.username="),
"SHADOW_EVIDENCE_USERNAME_REQUIRED");
assertStartupFailure(contextRunner.withPropertyValues(
"spring.profiles.active=shadow",
"shadow.enabled=true",
"shadow.source.jdbc-url=jdbc:h2:mem:source",
"shadow.evidence.jdbc-url=jdbc:h2:mem:evidence",
"shadow.source.username=source",
"shadow.evidence.username=evidence",
assertStartupFailure(configured(contextRunner).withPropertyValues(
"shadow.evidence.output-directory="),
"SHADOW_EVIDENCE_OUTPUT_DIRECTORY_REQUIRED");
assertStartupFailure(configured(contextRunner).withPropertyValues(
"shadow.evidence.minimum-free-bytes=-1"),
"SHADOW_EVIDENCE_MINIMUM_FREE_BYTES_INVALID");
assertStartupFailure(configured(contextRunner).withPropertyValues(
"shadow.evidence.run.artifact-sha256=invalid"),
"SHADOW_ARTIFACT_SHA256_INVALID");
assertStartupFailure(configured(contextRunner).withPropertyValues(
"shadow.evidence.run.configuration-sha256="),
"SHADOW_CONFIGURATION_SHA256_REQUIRED");
assertStartupFailure(configured(contextRunner).withPropertyValues(
"shadow.evidence.run.source-server="),
"SHADOW_SOURCE_SERVER_REQUIRED");
assertStartupFailure(configured(contextRunner).withPropertyValues(
"shadow.evidence.run.source-database="),
"SHADOW_SOURCE_DATABASE_REQUIRED");
assertStartupFailure(configured(contextRunner).withPropertyValues(
"server.address=0.0.0.0"),
"SHADOW_STATUS_ADDRESS_MUST_BE_LOOPBACK");
}
@@ -185,7 +232,14 @@ class Ft546ShadowApplicationTest {
"shadow.source.jdbc-url=jdbc:h2:mem:source",
"shadow.evidence.jdbc-url=jdbc:h2:mem:evidence",
"shadow.source.username=source",
"shadow.evidence.username=evidence");
"shadow.evidence.username=evidence",
"shadow.evidence.output-directory=.",
"shadow.evidence.minimum-free-bytes=0",
"shadow.evidence.run.artifact-sha256=" + ARTIFACT_SHA256,
"shadow.evidence.run.configuration-sha256="
+ CONFIGURATION_SHA256,
"shadow.evidence.run.source-server=ft546-test-server",
"shadow.evidence.run.source-database=ft546-test-source");
}
private static void assertStartupFailure(