feat: 一阶段
This commit is contained in:
123
src/test/java/com/codechecker/cache/MqScenarioTest.java
vendored
Normal file
123
src/test/java/com/codechecker/cache/MqScenarioTest.java
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
package com.codechecker.cache;
|
||||
|
||||
import com.codechecker.cache.detector.MqWritePointDetector;
|
||||
import com.codechecker.cache.detector.WritePoint;
|
||||
import com.codechecker.cache.diff.ChangeType;
|
||||
import com.codechecker.cache.diff.SchemaChange;
|
||||
import com.codechecker.cache.diff.SchemaDiffer;
|
||||
import com.codechecker.cache.report.CheckReport;
|
||||
import com.codechecker.cache.report.KeyStructureChange;
|
||||
import com.codechecker.cache.report.ReportBuilder;
|
||||
import com.codechecker.cache.schema.JavaSchemaExtractor;
|
||||
import com.codechecker.cache.schema.SourceIndex;
|
||||
import com.codechecker.cache.schema.TypeSchema;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
class MqScenarioTest {
|
||||
|
||||
@Test
|
||||
void rocketMqFieldRemovalProducesTopicDiff() {
|
||||
String constants = TestSupport.fixture("fixtures/mq/rocket-wallet/CapitalMqConstants.txt");
|
||||
String oldReq = TestSupport.fixture("fixtures/mq/rocket-wallet/WalletDeductReqOld.txt");
|
||||
String newReq = TestSupport.fixture("fixtures/mq/rocket-wallet/WalletDeductReqNew.txt");
|
||||
String producer = TestSupport.fixture("fixtures/mq/rocket-wallet/WalletDeductProducer.txt");
|
||||
|
||||
SourceIndex oldIndex = new SourceIndex();
|
||||
oldIndex.addSource(constants);
|
||||
oldIndex.addSource(oldReq);
|
||||
oldIndex.addSource(producer);
|
||||
|
||||
SourceIndex newIndex = new SourceIndex();
|
||||
newIndex.addSource(constants);
|
||||
newIndex.addSource(newReq);
|
||||
newIndex.addSource(producer);
|
||||
|
||||
Set<String> patterns = new HashSet<>();
|
||||
patterns.add("MQ01");
|
||||
WritePoint wp = new MqWritePointDetector(newIndex, patterns)
|
||||
.detect("WalletDeductProducer.java", producer).get(0);
|
||||
|
||||
TypeSchema oldSchema = new JavaSchemaExtractor(oldIndex, 8)
|
||||
.extract(wp.getResolvedValueType(), wp.isRootArray());
|
||||
TypeSchema newSchema = new JavaSchemaExtractor(newIndex, 8)
|
||||
.extract(wp.getResolvedValueType(), wp.isRootArray());
|
||||
List<SchemaChange> changes = new SchemaDiffer().diff(oldSchema, newSchema);
|
||||
List<ChangeType> types = changes.stream().map(SchemaChange::getChangeType).collect(Collectors.toList());
|
||||
assertTrue(types.contains(ChangeType.FIELD_REMOVED), "应删除 remark 字段");
|
||||
|
||||
CheckReport report = new CheckReport();
|
||||
report.setRepository("demo");
|
||||
report.setBranch("feature/mq");
|
||||
report.setOldSha("aaa");
|
||||
report.setNewSha("bbb");
|
||||
KeyStructureChange key = new KeyStructureChange();
|
||||
key.setKeyPattern(wp.getResolvedKeyPattern());
|
||||
key.setChannel(WritePoint.CHANNEL_ROCKETMQ);
|
||||
key.setWriteLocation(wp.location());
|
||||
key.setValueType("WalletDeductReq");
|
||||
key.setOldSkeletonJson("{\"walletId\":\"\",\"amount\":0,\"remark\":\"\"}");
|
||||
key.setNewSkeletonJson("{\"walletId\":\"\",\"amount\":0}");
|
||||
key.getFieldDetails().addAll(changes);
|
||||
report.getKeyChanges().add(key);
|
||||
report.getChanges().addAll(changes);
|
||||
|
||||
String md = new ReportBuilder("[序列化结构变更]").toMarkdown(report);
|
||||
assertTrue(md.contains("- Topic --> `capital-topic:WALLET_DEDUCT`"), md);
|
||||
assertTrue(md.contains("> **通道**: RocketMQ"), md);
|
||||
assertTrue(md.contains("<font color=\"warning\">\"remark\":\"\"</font>")
|
||||
|| md.contains("remark"), md);
|
||||
}
|
||||
|
||||
@Test
|
||||
void kafkaListFieldRemovalProducesTopicDiff() {
|
||||
String oldVo = TestSupport.fixture("fixtures/mq/kafka-patrol/CheckItemDetailVoOld.txt");
|
||||
String newVo = TestSupport.fixture("fixtures/mq/kafka-patrol/CheckItemDetailVoNew.txt");
|
||||
String service = TestSupport.fixture("fixtures/mq/kafka-patrol/PatrolService.txt");
|
||||
|
||||
SourceIndex oldIndex = new SourceIndex();
|
||||
oldIndex.addSource(oldVo);
|
||||
oldIndex.addSource(service);
|
||||
SourceIndex newIndex = new SourceIndex();
|
||||
newIndex.addSource(newVo);
|
||||
newIndex.addSource(service);
|
||||
|
||||
Set<String> patterns = new HashSet<>();
|
||||
patterns.add("MQ-K01");
|
||||
WritePoint wp = new MqWritePointDetector(newIndex, patterns)
|
||||
.detect("PatrolService.java", service).get(0);
|
||||
assertEquals("patrol-store-food-safe:*", wp.getResolvedKeyPattern());
|
||||
assertTrue(wp.isRootArray());
|
||||
|
||||
TypeSchema oldSchema = new JavaSchemaExtractor(oldIndex, 8)
|
||||
.extract(wp.getResolvedValueType(), true);
|
||||
TypeSchema newSchema = new JavaSchemaExtractor(newIndex, 8)
|
||||
.extract(wp.getResolvedValueType(), true);
|
||||
List<SchemaChange> changes = new SchemaDiffer().diff(oldSchema, newSchema);
|
||||
assertTrue(changes.stream().anyMatch(c -> c.getChangeType() == ChangeType.FIELD_REMOVED));
|
||||
|
||||
CheckReport report = new CheckReport();
|
||||
report.setRepository("demo");
|
||||
KeyStructureChange key = new KeyStructureChange();
|
||||
key.setKeyPattern(wp.getResolvedKeyPattern());
|
||||
key.setChannel(WritePoint.CHANNEL_KAFKA);
|
||||
key.setValueType("List<CheckItemDetailVo>");
|
||||
key.setWriteLocation(wp.location());
|
||||
key.setOldSkeletonJson("[{\"itemId\":\"\",\"itemName\":\"\",\"score\":0}]");
|
||||
key.setNewSkeletonJson("[{\"itemId\":\"\",\"itemName\":\"\"}]");
|
||||
key.getFieldDetails().addAll(changes);
|
||||
report.getKeyChanges().add(key);
|
||||
|
||||
String md = new ReportBuilder("[序列化结构变更]").toMarkdown(report);
|
||||
assertTrue(md.contains("- Topic --> `patrol-store-food-safe:*`"), md);
|
||||
assertTrue(md.contains("> **通道**: Kafka"), md);
|
||||
assertTrue(md.contains("> **类型**: List<CheckItemDetailVo>"), md);
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,9 @@ class ConfigLoaderTest {
|
||||
assertTrue(config.isEnabled());
|
||||
assertEquals("notify", config.getMode());
|
||||
assertTrue(config.getDetection().getPatterns().contains("W01"));
|
||||
assertTrue(config.getDetection().getMqPatterns().contains("MQ01"));
|
||||
assertTrue(config.getDetection().getMqPatterns().contains("MQ-K01"));
|
||||
assertFalse(config.getDetection().isMqReadHintsEnabled());
|
||||
assertFalse(config.isScanTestSources());
|
||||
}
|
||||
|
||||
|
||||
66
src/test/java/com/codechecker/cache/detector/MqWritePointDetectorTest.java
vendored
Normal file
66
src/test/java/com/codechecker/cache/detector/MqWritePointDetectorTest.java
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
package com.codechecker.cache.detector;
|
||||
|
||||
import com.codechecker.cache.TestSupport;
|
||||
import com.codechecker.cache.schema.SourceIndex;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
class MqWritePointDetectorTest {
|
||||
|
||||
@Test
|
||||
void detectsRocketMqSyncSendWithTopicTag() {
|
||||
String constants = TestSupport.fixture("fixtures/mq/rocket-wallet/CapitalMqConstants.txt");
|
||||
String req = TestSupport.fixture("fixtures/mq/rocket-wallet/WalletDeductReqOld.txt");
|
||||
String producer = TestSupport.fixture("fixtures/mq/rocket-wallet/WalletDeductProducer.txt");
|
||||
|
||||
SourceIndex index = new SourceIndex();
|
||||
index.addSource(constants);
|
||||
index.addSource(req);
|
||||
index.addSource(producer);
|
||||
|
||||
Set<String> patterns = new HashSet<>();
|
||||
patterns.add("MQ01");
|
||||
patterns.add("MQ02");
|
||||
List<WritePoint> wps = new MqWritePointDetector(index, patterns)
|
||||
.detect("WalletDeductProducer.java", producer);
|
||||
|
||||
assertEquals(1, wps.size());
|
||||
WritePoint wp = wps.get(0);
|
||||
assertEquals("MQ01", wp.getPattern());
|
||||
assertEquals(WritePoint.CHANNEL_ROCKETMQ, wp.getChannel());
|
||||
assertEquals("capital-topic:WALLET_DEDUCT", wp.getResolvedKeyPattern());
|
||||
assertTrue(wp.getResolvedValueType().endsWith("WalletDeductReq"));
|
||||
assertFalse(wp.isRootArray());
|
||||
}
|
||||
|
||||
@Test
|
||||
void detectsKafkaSendListAsRootArray() {
|
||||
String vo = TestSupport.fixture("fixtures/mq/kafka-patrol/CheckItemDetailVoOld.txt");
|
||||
String service = TestSupport.fixture("fixtures/mq/kafka-patrol/PatrolService.txt");
|
||||
|
||||
SourceIndex index = new SourceIndex();
|
||||
index.addSource(vo);
|
||||
index.addSource(service);
|
||||
|
||||
Set<String> patterns = new HashSet<>();
|
||||
patterns.add("MQ-K01");
|
||||
patterns.add("MQ-K02");
|
||||
List<WritePoint> wps = new MqWritePointDetector(index, patterns)
|
||||
.detect("PatrolService.java", service);
|
||||
|
||||
assertEquals(1, wps.size());
|
||||
WritePoint wp = wps.get(0);
|
||||
assertEquals("MQ-K01", wp.getPattern());
|
||||
assertEquals(WritePoint.CHANNEL_KAFKA, wp.getChannel());
|
||||
assertEquals("patrol-store-food-safe:*", wp.getResolvedKeyPattern());
|
||||
assertTrue(wp.getResolvedValueType().endsWith("CheckItemDetailVo"));
|
||||
assertTrue(wp.isRootArray());
|
||||
}
|
||||
}
|
||||
@@ -168,6 +168,37 @@ class ReportBuilderTest {
|
||||
"应包含类型变更摘要行,实际 markdown:\n" + md);
|
||||
}
|
||||
|
||||
@Test
|
||||
void typeChangeSummaryDedupesSameFieldFromMultipleWrites() {
|
||||
CheckReport report = baseReport();
|
||||
KeyStructureChange key = new KeyStructureChange();
|
||||
key.setKeyPattern("data-analysis-task-topic");
|
||||
key.setChannel("ROCKETMQ");
|
||||
key.setWriteLocation("FtbDataAnalysisTaskServiceImpl#createTasks:48");
|
||||
key.setValueType("DataAnalysisBO");
|
||||
key.setOldSkeletonJson("{\"test1\":\"\"}");
|
||||
key.setNewSkeletonJson("{\"test1\":0}");
|
||||
|
||||
SchemaChange a = new SchemaChange(ChangeType.TYPE_CHANGED);
|
||||
a.setFieldPath("test1");
|
||||
a.setOldValue("String/STRING");
|
||||
a.setNewValue("Integer/NUMBER");
|
||||
a.setWriteLocation("FtbDataAnalysisTaskServiceImpl#createTasks:48");
|
||||
SchemaChange b = new SchemaChange(ChangeType.TYPE_CHANGED);
|
||||
b.setFieldPath("test1");
|
||||
b.setOldValue("String/STRING");
|
||||
b.setNewValue("Integer/NUMBER");
|
||||
b.setWriteLocation("FtbDataAnalysisTaskServiceImpl#createTasks:52");
|
||||
key.getFieldDetails().add(a);
|
||||
key.getFieldDetails().add(b);
|
||||
report.getKeyChanges().add(key);
|
||||
|
||||
String md = new ReportBuilder("[序列化结构变更]").toMarkdown(report);
|
||||
assertTrue(md.contains("> **类型变更**: test1 <font color=\"warning\">String → Integer</font>"), md);
|
||||
assertFalse(md.contains("String → Integer</font>;test1"),
|
||||
"同字段类型变更不应重复,实际:\n" + md);
|
||||
}
|
||||
|
||||
@Test
|
||||
void wrapperAddedHighlightedBeforeNestedMovedFields() {
|
||||
SchemaChange wrapper = new SchemaChange(ChangeType.WRAPPER_ADDED);
|
||||
|
||||
Reference in New Issue
Block a user