All checks were successful
序列化结构检查 / serialization-schema-check (push) Has been skipped
151 lines
7.1 KiB
Java
151 lines
7.1 KiB
Java
package com.codechecker.cache.diff;
|
||
|
||
import com.codechecker.cache.schema.FieldSchema;
|
||
import com.codechecker.cache.schema.JsonType;
|
||
import com.codechecker.cache.schema.TypeSchema;
|
||
import org.junit.jupiter.api.Test;
|
||
|
||
import java.util.List;
|
||
import java.util.stream.Collectors;
|
||
|
||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||
|
||
class SchemaDifferTest {
|
||
|
||
@Test
|
||
void detectsWrapperMoveAndAddition() {
|
||
TypeSchema oldS = new TypeSchema("TenantVO");
|
||
oldS.add(new FieldSchema("dbName", JsonType.STRING, "String"));
|
||
oldS.add(new FieldSchema("linkList", JsonType.ARRAY, "List"));
|
||
oldS.add(new FieldSchema("linkList[]", JsonType.OBJECT, "TenantLinkModel"));
|
||
oldS.add(new FieldSchema("linkList[].id", JsonType.STRING, "String"));
|
||
|
||
TypeSchema newS = new TypeSchema("CacheEnvelope");
|
||
newS.add(new FieldSchema("vo", JsonType.OBJECT, "TenantVO"));
|
||
newS.add(new FieldSchema("vo.dbName", JsonType.STRING, "String"));
|
||
newS.add(new FieldSchema("vo.linkList", JsonType.ARRAY, "List"));
|
||
newS.add(new FieldSchema("vo.linkList[]", JsonType.OBJECT, "TenantLinkModel"));
|
||
newS.add(new FieldSchema("vo.linkList[].id", JsonType.STRING, "String"));
|
||
newS.add(new FieldSchema("expiresAtMs", JsonType.NUMBER, "Long"));
|
||
|
||
List<SchemaChange> changes = new SchemaDiffer().diff(oldS, newS);
|
||
List<ChangeType> types = changes.stream().map(SchemaChange::getChangeType).collect(Collectors.toList());
|
||
|
||
assertTrue(types.contains(ChangeType.WRAPPER_ADDED), "应检测到包装层新增");
|
||
assertTrue(types.contains(ChangeType.FIELD_PATH_MOVED), "应检测到字段路径迁移");
|
||
assertTrue(types.contains(ChangeType.FIELD_ADDED), "应检测到新增字段 expiresAtMs");
|
||
|
||
long moved = changes.stream().filter(c -> c.getChangeType() == ChangeType.FIELD_PATH_MOVED).count();
|
||
assertEquals(2, moved, "dbName 与 linkList[].id 均应迁移");
|
||
}
|
||
|
||
@Test
|
||
void detectsWrapperRemovalAndUpwardMoves() {
|
||
TypeSchema oldS = new TypeSchema("CacheEnvelope");
|
||
oldS.add(new FieldSchema("vo", JsonType.OBJECT, "TenantVO"));
|
||
oldS.add(new FieldSchema("vo.dbName", JsonType.STRING, "String"));
|
||
oldS.add(new FieldSchema("vo.linkList", JsonType.ARRAY, "List"));
|
||
oldS.add(new FieldSchema("vo.linkList[]", JsonType.OBJECT, "TenantLinkModel"));
|
||
oldS.add(new FieldSchema("vo.linkList[].id", JsonType.STRING, "String"));
|
||
|
||
TypeSchema newS = new TypeSchema("TenantVO");
|
||
newS.add(new FieldSchema("dbName", JsonType.STRING, "String"));
|
||
newS.add(new FieldSchema("linkList", JsonType.ARRAY, "List"));
|
||
newS.add(new FieldSchema("linkList[]", JsonType.OBJECT, "TenantLinkModel"));
|
||
newS.add(new FieldSchema("linkList[].id", JsonType.STRING, "String"));
|
||
|
||
List<SchemaChange> changes = new SchemaDiffer().diff(oldS, newS);
|
||
List<ChangeType> types = changes.stream().map(SchemaChange::getChangeType).collect(Collectors.toList());
|
||
|
||
assertTrue(types.contains(ChangeType.WRAPPER_REMOVED), "应检测到包装层删除");
|
||
assertTrue(types.contains(ChangeType.FIELD_PATH_MOVED), "应检测到字段上提迁移");
|
||
assertTrue(types.stream().noneMatch(t -> t == ChangeType.FIELD_ADDED),
|
||
"上提字段不应再被当成新增");
|
||
assertTrue(types.stream().noneMatch(t -> t == ChangeType.FIELD_REMOVED),
|
||
"上提字段不应再被当成删除");
|
||
|
||
SchemaChange wrapper = changes.stream()
|
||
.filter(c -> c.getChangeType() == ChangeType.WRAPPER_REMOVED)
|
||
.findFirst()
|
||
.orElseThrow(IllegalStateException::new);
|
||
assertEquals("vo", wrapper.getFieldPath());
|
||
|
||
long moved = changes.stream().filter(c -> c.getChangeType() == ChangeType.FIELD_PATH_MOVED).count();
|
||
assertEquals(2, moved, "vo.dbName / vo.linkList[].id 均应上提");
|
||
}
|
||
|
||
@Test
|
||
void detectsTypeChange() {
|
||
TypeSchema oldS = new TypeSchema("A");
|
||
oldS.add(new FieldSchema("count", JsonType.STRING, "String"));
|
||
TypeSchema newS = new TypeSchema("A");
|
||
newS.add(new FieldSchema("count", JsonType.NUMBER, "Integer"));
|
||
|
||
List<SchemaChange> changes = new SchemaDiffer().diff(oldS, newS);
|
||
assertEquals(1, changes.size());
|
||
assertEquals(ChangeType.TYPE_CHANGED, changes.get(0).getChangeType());
|
||
assertEquals(Severity.P0, changes.get(0).getSeverity());
|
||
assertTrue(changes.get(0).getMessage().contains("String"));
|
||
assertTrue(changes.get(0).getMessage().contains("Integer"));
|
||
}
|
||
|
||
@Test
|
||
void detectsBigDecimalToStringEvenWhenBothWereStringBucketHistorically() {
|
||
// 即便 JsonType 同为 STRING,javaType 变化也必须检出(用户真实漏报场景)
|
||
TypeSchema oldS = new TypeSchema("A");
|
||
oldS.add(new FieldSchema("amount", JsonType.STRING, "BigDecimal"));
|
||
TypeSchema newS = new TypeSchema("A");
|
||
newS.add(new FieldSchema("amount", JsonType.STRING, "String"));
|
||
|
||
List<SchemaChange> changes = new SchemaDiffer().diff(oldS, newS);
|
||
assertEquals(1, changes.size());
|
||
assertEquals(ChangeType.TYPE_CHANGED, changes.get(0).getChangeType());
|
||
assertEquals("amount", changes.get(0).getFieldPath());
|
||
assertTrue(changes.get(0).getOldValue().contains("BigDecimal"));
|
||
assertTrue(changes.get(0).getNewValue().contains("String"));
|
||
}
|
||
|
||
@Test
|
||
void detectsBigDecimalToStringViaJsonTypeAndJavaType() {
|
||
TypeSchema oldS = new TypeSchema("A");
|
||
oldS.add(new FieldSchema("amount", JsonType.NUMBER, "BigDecimal"));
|
||
TypeSchema newS = new TypeSchema("A");
|
||
newS.add(new FieldSchema("amount", JsonType.STRING, "String"));
|
||
|
||
List<SchemaChange> changes = new SchemaDiffer().diff(oldS, newS);
|
||
assertEquals(1, changes.size());
|
||
assertEquals(ChangeType.TYPE_CHANGED, changes.get(0).getChangeType());
|
||
}
|
||
|
||
@Test
|
||
void detectsIntegerToLongWithinNumberBucket() {
|
||
TypeSchema oldS = new TypeSchema("A");
|
||
oldS.add(new FieldSchema("id", JsonType.NUMBER, "Integer"));
|
||
TypeSchema newS = new TypeSchema("A");
|
||
newS.add(new FieldSchema("id", JsonType.NUMBER, "Long"));
|
||
|
||
List<SchemaChange> changes = new SchemaDiffer().diff(oldS, newS);
|
||
assertEquals(1, changes.size());
|
||
assertEquals(ChangeType.TYPE_CHANGED, changes.get(0).getChangeType());
|
||
}
|
||
|
||
@Test
|
||
void noChangeWhenPrimitiveAndWrapperEquivalent() {
|
||
TypeSchema a = new TypeSchema("A");
|
||
a.add(new FieldSchema("n", JsonType.NUMBER, "int"));
|
||
TypeSchema b = new TypeSchema("A");
|
||
b.add(new FieldSchema("n", JsonType.NUMBER, "Integer"));
|
||
assertTrue(new SchemaDiffer().diff(a, b).isEmpty());
|
||
}
|
||
|
||
@Test
|
||
void noChangeWhenIdentical() {
|
||
TypeSchema a = new TypeSchema("A");
|
||
a.add(new FieldSchema("x", JsonType.STRING, "String"));
|
||
TypeSchema b = new TypeSchema("A");
|
||
b.add(new FieldSchema("x", JsonType.STRING, "String"));
|
||
assertTrue(new SchemaDiffer().diff(a, b).isEmpty());
|
||
}
|
||
}
|