test: centralize vehicle identity fixtures
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
|
||||
## 设计目标
|
||||
|
||||
- **协议接入统一抽象**:GB/T 32960、JT/T 808、Yutong MQTT 是默认生产接入;JT/T 1078、JSATL12 作为显式 profile 的可选能力;信达 Push 仅保留为废弃兼容模块
|
||||
- **协议接入统一抽象**:GB/T 32960、JT/T 808、Yutong MQTT 是默认生产接入;JT/T 1078、JSATL12 作为显式 profile 的可选能力;信达 Push 已废弃并删除源码
|
||||
- **原子能力化**:每个协议一个独立 Maven 模块 + 独立 AutoConfiguration + 独立配置开关
|
||||
- **业务 / 实时彻底解耦**:协议接入应用只负责收、解析、校验、规整和投递 Kafka;历史与统计由独立 Kafka 消费应用落库
|
||||
- **高并发低延迟**:Netty + Disruptor + Java 25 虚拟线程;目标单节点 ≥ 5 万 msg/s,P99 < 50 ms
|
||||
@@ -53,6 +53,8 @@ lingniu-vehicle-ingest/
|
||||
│ │ ├── event-history-service/ Kafka 全字段事件消费 + 历史查询
|
||||
│ │ ├── vehicle-state-service/ Kafka 全字段事件消费 + Redis 热状态查询(optional-latest-state profile)
|
||||
│ │ └── vehicle-stat-service/ Kafka 全字段事件消费 + 可配置日统计
|
||||
│ ├── testing/
|
||||
│ │ └── vehicle-identity-test-support/ 协议测试共享身份解析夹具
|
||||
│ └── apps/
|
||||
│ ├── command-gateway/ 可选 HTTP → 设备下行命令(optional-command-gateway profile)
|
||||
│ ├── gb32960-ingest-app/ GB32960 TCP 接入 + Kafka 投递
|
||||
|
||||
@@ -122,6 +122,7 @@ class MavenModuleProfileTest {
|
||||
void xindaModulesAreRemovedFromBuildSurface() throws Exception {
|
||||
Document pom = rootPom();
|
||||
String rootPomText = Files.readString(repositoryRoot().resolve("pom.xml"));
|
||||
String readme = Files.readString(repositoryRoot().resolve("README.md"));
|
||||
|
||||
assertThat(defaultModules(pom))
|
||||
.doesNotContain("modules/inbound/inbound-xinda-push")
|
||||
@@ -137,6 +138,10 @@ class MavenModuleProfileTest {
|
||||
.doesNotContain("legacy-xinda")
|
||||
.doesNotContain("inbound-xinda-push")
|
||||
.doesNotContain("xinda-push-app");
|
||||
assertThat(readme)
|
||||
.contains("信达 Push 已废弃并删除源码")
|
||||
.doesNotContain("信达 Push 仅保留")
|
||||
.doesNotContain("废弃兼容模块");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -187,6 +192,29 @@ class MavenModuleProfileTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void vehicleIdentityTestSupportIsCentralizedInsteadOfCopiedIntoProtocolTests() throws Exception {
|
||||
Document pom = rootPom();
|
||||
List<String> testSupportFixtures = javaFilesNamed("InMemoryVehicleIdentityService.java");
|
||||
|
||||
assertThat(defaultModules(pom))
|
||||
.contains("modules/testing/vehicle-identity-test-support");
|
||||
assertThat(rootDependencyManagementArtifacts(pom))
|
||||
.contains("vehicle-identity-test-support");
|
||||
assertThat(testSupportFixtures)
|
||||
.containsExactly("modules/testing/vehicle-identity-test-support/src/main/java/com/lingniu/ingest/identity/InMemoryVehicleIdentityService.java");
|
||||
|
||||
for (String modulePom : List.of(
|
||||
"modules/protocols/protocol-jt808/pom.xml",
|
||||
"modules/inbound/inbound-mqtt/pom.xml",
|
||||
"modules/protocols/protocol-jt1078/pom.xml",
|
||||
"modules/protocols/protocol-jsatl12/pom.xml")) {
|
||||
assertThat(hasDependency(modulePom(modulePom), "com.lingniu.ingest", "vehicle-identity-test-support"))
|
||||
.as(modulePom)
|
||||
.isTrue();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void readmeMatchesCurrentRuntimeVersionsAndSplitAppResponsibilities() throws Exception {
|
||||
Document pom = rootPom();
|
||||
@@ -798,6 +826,19 @@ class MavenModuleProfileTest {
|
||||
}
|
||||
}
|
||||
|
||||
private static List<String> javaFilesNamed(String fileName) throws Exception {
|
||||
Path root = repositoryRoot();
|
||||
try (Stream<Path> files = Files.walk(root.resolve("modules"))) {
|
||||
return files
|
||||
.filter(Files::isRegularFile)
|
||||
.filter(path -> fileName.equals(path.getFileName().toString()))
|
||||
.map(root::relativize)
|
||||
.map(Path::toString)
|
||||
.sorted()
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
|
||||
private static Element firstDirectChild(Element parent, String tagName) {
|
||||
NodeList children = parent.getChildNodes();
|
||||
for (int i = 0; i < children.getLength(); i++) {
|
||||
|
||||
@@ -24,6 +24,11 @@
|
||||
<groupId>com.lingniu.ingest</groupId>
|
||||
<artifactId>vehicle-identity</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.lingniu.ingest</groupId>
|
||||
<artifactId>vehicle-identity-test-support</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
|
||||
@@ -31,6 +31,11 @@
|
||||
<groupId>com.lingniu.ingest</groupId>
|
||||
<artifactId>vehicle-identity</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.lingniu.ingest</groupId>
|
||||
<artifactId>vehicle-identity-test-support</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.lingniu.ingest</groupId>
|
||||
<artifactId>sink-archive</artifactId>
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
package com.lingniu.ingest.identity;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
public final class InMemoryVehicleIdentityService implements VehicleIdentityResolver, VehicleIdentityRegistry {
|
||||
|
||||
private final List<VehicleIdentityBinding> bindings = new CopyOnWriteArrayList<>();
|
||||
|
||||
@Override
|
||||
public VehicleIdentity resolve(VehicleIdentityLookup lookup) {
|
||||
if (lookup == null) {
|
||||
return new VehicleIdentity("unknown", false, VehicleIdentitySource.UNKNOWN);
|
||||
}
|
||||
if (!lookup.vin().isBlank() && !"unknown".equalsIgnoreCase(lookup.vin())) {
|
||||
return new VehicleIdentity(lookup.vin(), true, VehicleIdentitySource.EXPLICIT_VIN);
|
||||
}
|
||||
for (VehicleIdentityBinding binding : bindings) {
|
||||
if (binding.protocol() != lookup.protocol()) {
|
||||
continue;
|
||||
}
|
||||
if (!lookup.phone().isBlank() && lookup.phone().equals(binding.phone())) {
|
||||
return new VehicleIdentity(binding.vin(), true, VehicleIdentitySource.BOUND_PHONE);
|
||||
}
|
||||
if (!lookup.deviceId().isBlank() && lookup.deviceId().equals(binding.deviceId())) {
|
||||
return new VehicleIdentity(binding.vin(), true, VehicleIdentitySource.BOUND_DEVICE_ID);
|
||||
}
|
||||
if (!lookup.plate().isBlank() && lookup.plate().equals(binding.plate())) {
|
||||
return new VehicleIdentity(binding.vin(), true, VehicleIdentitySource.BOUND_PLATE);
|
||||
}
|
||||
}
|
||||
if (!lookup.phone().isBlank()) {
|
||||
return new VehicleIdentity("unknown", false, VehicleIdentitySource.FALLBACK_PHONE);
|
||||
}
|
||||
if (!lookup.deviceId().isBlank()) {
|
||||
return new VehicleIdentity("unknown", false, VehicleIdentitySource.FALLBACK_DEVICE_ID);
|
||||
}
|
||||
if (!lookup.plate().isBlank()) {
|
||||
return new VehicleIdentity("unknown", false, VehicleIdentitySource.FALLBACK_PLATE);
|
||||
}
|
||||
return new VehicleIdentity("unknown", false, VehicleIdentitySource.UNKNOWN);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bind(VehicleIdentityBinding binding) {
|
||||
bindings.add(binding);
|
||||
}
|
||||
}
|
||||
@@ -31,6 +31,11 @@
|
||||
<groupId>com.lingniu.ingest</groupId>
|
||||
<artifactId>vehicle-identity</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.lingniu.ingest</groupId>
|
||||
<artifactId>vehicle-identity-test-support</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.lingniu.ingest</groupId>
|
||||
<artifactId>sink-archive</artifactId>
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
package com.lingniu.ingest.identity;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
public final class InMemoryVehicleIdentityService implements VehicleIdentityResolver, VehicleIdentityRegistry {
|
||||
|
||||
private final List<VehicleIdentityBinding> bindings = new CopyOnWriteArrayList<>();
|
||||
|
||||
@Override
|
||||
public VehicleIdentity resolve(VehicleIdentityLookup lookup) {
|
||||
if (lookup == null) {
|
||||
return new VehicleIdentity("unknown", false, VehicleIdentitySource.UNKNOWN);
|
||||
}
|
||||
if (!lookup.vin().isBlank() && !"unknown".equalsIgnoreCase(lookup.vin())) {
|
||||
return new VehicleIdentity(lookup.vin(), true, VehicleIdentitySource.EXPLICIT_VIN);
|
||||
}
|
||||
for (VehicleIdentityBinding binding : bindings) {
|
||||
if (binding.protocol() != lookup.protocol()) {
|
||||
continue;
|
||||
}
|
||||
if (!lookup.phone().isBlank() && lookup.phone().equals(binding.phone())) {
|
||||
return new VehicleIdentity(binding.vin(), true, VehicleIdentitySource.BOUND_PHONE);
|
||||
}
|
||||
if (!lookup.deviceId().isBlank() && lookup.deviceId().equals(binding.deviceId())) {
|
||||
return new VehicleIdentity(binding.vin(), true, VehicleIdentitySource.BOUND_DEVICE_ID);
|
||||
}
|
||||
if (!lookup.plate().isBlank() && lookup.plate().equals(binding.plate())) {
|
||||
return new VehicleIdentity(binding.vin(), true, VehicleIdentitySource.BOUND_PLATE);
|
||||
}
|
||||
}
|
||||
if (!lookup.phone().isBlank()) {
|
||||
return new VehicleIdentity("unknown", false, VehicleIdentitySource.FALLBACK_PHONE);
|
||||
}
|
||||
if (!lookup.deviceId().isBlank()) {
|
||||
return new VehicleIdentity("unknown", false, VehicleIdentitySource.FALLBACK_DEVICE_ID);
|
||||
}
|
||||
if (!lookup.plate().isBlank()) {
|
||||
return new VehicleIdentity("unknown", false, VehicleIdentitySource.FALLBACK_PLATE);
|
||||
}
|
||||
return new VehicleIdentity("unknown", false, VehicleIdentitySource.UNKNOWN);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bind(VehicleIdentityBinding binding) {
|
||||
bindings.add(binding);
|
||||
}
|
||||
}
|
||||
@@ -32,6 +32,11 @@
|
||||
<groupId>com.lingniu.ingest</groupId>
|
||||
<artifactId>vehicle-identity</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.lingniu.ingest</groupId>
|
||||
<artifactId>vehicle-identity-test-support</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
package com.lingniu.ingest.identity;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
public final class InMemoryVehicleIdentityService implements VehicleIdentityResolver, VehicleIdentityRegistry {
|
||||
|
||||
private final List<VehicleIdentityBinding> bindings = new CopyOnWriteArrayList<>();
|
||||
|
||||
@Override
|
||||
public VehicleIdentity resolve(VehicleIdentityLookup lookup) {
|
||||
if (lookup == null) {
|
||||
return new VehicleIdentity("unknown", false, VehicleIdentitySource.UNKNOWN);
|
||||
}
|
||||
if (!lookup.vin().isBlank() && !"unknown".equalsIgnoreCase(lookup.vin())) {
|
||||
return new VehicleIdentity(lookup.vin(), true, VehicleIdentitySource.EXPLICIT_VIN);
|
||||
}
|
||||
for (VehicleIdentityBinding binding : bindings) {
|
||||
if (binding.protocol() != lookup.protocol()) {
|
||||
continue;
|
||||
}
|
||||
if (!lookup.phone().isBlank() && lookup.phone().equals(binding.phone())) {
|
||||
return new VehicleIdentity(binding.vin(), true, VehicleIdentitySource.BOUND_PHONE);
|
||||
}
|
||||
if (!lookup.deviceId().isBlank() && lookup.deviceId().equals(binding.deviceId())) {
|
||||
return new VehicleIdentity(binding.vin(), true, VehicleIdentitySource.BOUND_DEVICE_ID);
|
||||
}
|
||||
if (!lookup.plate().isBlank() && lookup.plate().equals(binding.plate())) {
|
||||
return new VehicleIdentity(binding.vin(), true, VehicleIdentitySource.BOUND_PLATE);
|
||||
}
|
||||
}
|
||||
if (!lookup.phone().isBlank()) {
|
||||
return new VehicleIdentity("unknown", false, VehicleIdentitySource.FALLBACK_PHONE);
|
||||
}
|
||||
if (!lookup.deviceId().isBlank()) {
|
||||
return new VehicleIdentity("unknown", false, VehicleIdentitySource.FALLBACK_DEVICE_ID);
|
||||
}
|
||||
if (!lookup.plate().isBlank()) {
|
||||
return new VehicleIdentity("unknown", false, VehicleIdentitySource.FALLBACK_PLATE);
|
||||
}
|
||||
return new VehicleIdentity("unknown", false, VehicleIdentitySource.UNKNOWN);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bind(VehicleIdentityBinding binding) {
|
||||
bindings.add(binding);
|
||||
}
|
||||
}
|
||||
20
modules/testing/vehicle-identity-test-support/pom.xml
Normal file
20
modules/testing/vehicle-identity-test-support/pom.xml
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.lingniu.ingest</groupId>
|
||||
<artifactId>lingniu-vehicle-ingest</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>vehicle-identity-test-support</artifactId>
|
||||
<name>vehicle-identity-test-support</name>
|
||||
<description>车辆身份解析测试夹具,仅供协议和接入模块测试依赖。</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.lingniu.ingest</groupId>
|
||||
<artifactId>vehicle-identity</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -29,14 +29,14 @@ public final class InMemoryVehicleIdentityService implements VehicleIdentityReso
|
||||
return new VehicleIdentity(binding.vin(), true, VehicleIdentitySource.BOUND_PLATE);
|
||||
}
|
||||
}
|
||||
if (!lookup.phone().isBlank()) {
|
||||
return new VehicleIdentity("unknown", false, VehicleIdentitySource.FALLBACK_PHONE);
|
||||
}
|
||||
if (!lookup.deviceId().isBlank()) {
|
||||
return new VehicleIdentity("unknown", false, VehicleIdentitySource.FALLBACK_DEVICE_ID);
|
||||
return new VehicleIdentity(lookup.deviceId(), false, VehicleIdentitySource.FALLBACK_DEVICE_ID);
|
||||
}
|
||||
if (!lookup.phone().isBlank()) {
|
||||
return new VehicleIdentity(lookup.phone(), false, VehicleIdentitySource.FALLBACK_PHONE);
|
||||
}
|
||||
if (!lookup.plate().isBlank()) {
|
||||
return new VehicleIdentity("unknown", false, VehicleIdentitySource.FALLBACK_PLATE);
|
||||
return new VehicleIdentity(lookup.plate(), false, VehicleIdentitySource.FALLBACK_PLATE);
|
||||
}
|
||||
return new VehicleIdentity("unknown", false, VehicleIdentitySource.UNKNOWN);
|
||||
}
|
||||
6
pom.xml
6
pom.xml
@@ -23,6 +23,7 @@
|
||||
<module>modules/core/ingest-core</module>
|
||||
<module>modules/core/session-core</module>
|
||||
<module>modules/core/vehicle-identity</module>
|
||||
<module>modules/testing/vehicle-identity-test-support</module>
|
||||
<module>modules/core/observability</module>
|
||||
<module>modules/sinks/sink-kafka</module>
|
||||
<module>modules/sinks/sink-archive</module>
|
||||
@@ -201,6 +202,11 @@
|
||||
<artifactId>vehicle-identity</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.lingniu.ingest</groupId>
|
||||
<artifactId>vehicle-identity-test-support</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.lingniu.ingest</groupId>
|
||||
<artifactId>observability</artifactId>
|
||||
|
||||
Reference in New Issue
Block a user