From e06534d6a52d0ee79c3324c3b74dec9ef4e840e3 Mon Sep 17 00:00:00 2001 From: lingniu Date: Wed, 1 Jul 2026 18:32:09 +0800 Subject: [PATCH] test: centralize vehicle identity fixtures --- README.md | 4 +- .../historyapp/MavenModuleProfileTest.java | 41 ++++++++++++++++ modules/inbound/inbound-mqtt/pom.xml | 5 ++ modules/protocols/protocol-jsatl12/pom.xml | 5 ++ .../InMemoryVehicleIdentityService.java | 48 ------------------- modules/protocols/protocol-jt1078/pom.xml | 5 ++ .../InMemoryVehicleIdentityService.java | 48 ------------------- modules/protocols/protocol-jt808/pom.xml | 5 ++ .../InMemoryVehicleIdentityService.java | 48 ------------------- .../vehicle-identity-test-support/pom.xml | 20 ++++++++ .../InMemoryVehicleIdentityService.java | 10 ++-- pom.xml | 6 +++ 12 files changed, 95 insertions(+), 150 deletions(-) delete mode 100644 modules/protocols/protocol-jsatl12/src/test/java/com/lingniu/ingest/identity/InMemoryVehicleIdentityService.java delete mode 100644 modules/protocols/protocol-jt1078/src/test/java/com/lingniu/ingest/identity/InMemoryVehicleIdentityService.java delete mode 100644 modules/protocols/protocol-jt808/src/test/java/com/lingniu/ingest/identity/InMemoryVehicleIdentityService.java create mode 100644 modules/testing/vehicle-identity-test-support/pom.xml rename modules/{inbound/inbound-mqtt/src/test => testing/vehicle-identity-test-support/src/main}/java/com/lingniu/ingest/identity/InMemoryVehicleIdentityService.java (85%) diff --git a/README.md b/README.md index 8e2976b6..bad5be4d 100644 --- a/README.md +++ b/README.md @@ -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 投递 diff --git a/modules/apps/vehicle-history-app/src/test/java/com/lingniu/ingest/historyapp/MavenModuleProfileTest.java b/modules/apps/vehicle-history-app/src/test/java/com/lingniu/ingest/historyapp/MavenModuleProfileTest.java index b1759268..0b8cde7e 100644 --- a/modules/apps/vehicle-history-app/src/test/java/com/lingniu/ingest/historyapp/MavenModuleProfileTest.java +++ b/modules/apps/vehicle-history-app/src/test/java/com/lingniu/ingest/historyapp/MavenModuleProfileTest.java @@ -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 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 javaFilesNamed(String fileName) throws Exception { + Path root = repositoryRoot(); + try (Stream 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++) { diff --git a/modules/inbound/inbound-mqtt/pom.xml b/modules/inbound/inbound-mqtt/pom.xml index 8bcbe7b3..d5efad2d 100644 --- a/modules/inbound/inbound-mqtt/pom.xml +++ b/modules/inbound/inbound-mqtt/pom.xml @@ -24,6 +24,11 @@ com.lingniu.ingest vehicle-identity + + com.lingniu.ingest + vehicle-identity-test-support + test + org.springframework.boot spring-boot-starter diff --git a/modules/protocols/protocol-jsatl12/pom.xml b/modules/protocols/protocol-jsatl12/pom.xml index b84358d4..b922c0e2 100644 --- a/modules/protocols/protocol-jsatl12/pom.xml +++ b/modules/protocols/protocol-jsatl12/pom.xml @@ -31,6 +31,11 @@ com.lingniu.ingest vehicle-identity + + com.lingniu.ingest + vehicle-identity-test-support + test + com.lingniu.ingest sink-archive diff --git a/modules/protocols/protocol-jsatl12/src/test/java/com/lingniu/ingest/identity/InMemoryVehicleIdentityService.java b/modules/protocols/protocol-jsatl12/src/test/java/com/lingniu/ingest/identity/InMemoryVehicleIdentityService.java deleted file mode 100644 index f30866f6..00000000 --- a/modules/protocols/protocol-jsatl12/src/test/java/com/lingniu/ingest/identity/InMemoryVehicleIdentityService.java +++ /dev/null @@ -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 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); - } -} diff --git a/modules/protocols/protocol-jt1078/pom.xml b/modules/protocols/protocol-jt1078/pom.xml index bc0e0643..4110d5ec 100644 --- a/modules/protocols/protocol-jt1078/pom.xml +++ b/modules/protocols/protocol-jt1078/pom.xml @@ -31,6 +31,11 @@ com.lingniu.ingest vehicle-identity + + com.lingniu.ingest + vehicle-identity-test-support + test + com.lingniu.ingest sink-archive diff --git a/modules/protocols/protocol-jt1078/src/test/java/com/lingniu/ingest/identity/InMemoryVehicleIdentityService.java b/modules/protocols/protocol-jt1078/src/test/java/com/lingniu/ingest/identity/InMemoryVehicleIdentityService.java deleted file mode 100644 index f30866f6..00000000 --- a/modules/protocols/protocol-jt1078/src/test/java/com/lingniu/ingest/identity/InMemoryVehicleIdentityService.java +++ /dev/null @@ -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 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); - } -} diff --git a/modules/protocols/protocol-jt808/pom.xml b/modules/protocols/protocol-jt808/pom.xml index de8766a7..efcaadfd 100644 --- a/modules/protocols/protocol-jt808/pom.xml +++ b/modules/protocols/protocol-jt808/pom.xml @@ -32,6 +32,11 @@ com.lingniu.ingest vehicle-identity + + com.lingniu.ingest + vehicle-identity-test-support + test + org.springframework.boot spring-boot-starter diff --git a/modules/protocols/protocol-jt808/src/test/java/com/lingniu/ingest/identity/InMemoryVehicleIdentityService.java b/modules/protocols/protocol-jt808/src/test/java/com/lingniu/ingest/identity/InMemoryVehicleIdentityService.java deleted file mode 100644 index f30866f6..00000000 --- a/modules/protocols/protocol-jt808/src/test/java/com/lingniu/ingest/identity/InMemoryVehicleIdentityService.java +++ /dev/null @@ -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 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); - } -} diff --git a/modules/testing/vehicle-identity-test-support/pom.xml b/modules/testing/vehicle-identity-test-support/pom.xml new file mode 100644 index 00000000..31fad0dc --- /dev/null +++ b/modules/testing/vehicle-identity-test-support/pom.xml @@ -0,0 +1,20 @@ + + + 4.0.0 + + com.lingniu.ingest + lingniu-vehicle-ingest + 0.1.0-SNAPSHOT + ../../../pom.xml + + vehicle-identity-test-support + vehicle-identity-test-support + 车辆身份解析测试夹具,仅供协议和接入模块测试依赖。 + + + + com.lingniu.ingest + vehicle-identity + + + diff --git a/modules/inbound/inbound-mqtt/src/test/java/com/lingniu/ingest/identity/InMemoryVehicleIdentityService.java b/modules/testing/vehicle-identity-test-support/src/main/java/com/lingniu/ingest/identity/InMemoryVehicleIdentityService.java similarity index 85% rename from modules/inbound/inbound-mqtt/src/test/java/com/lingniu/ingest/identity/InMemoryVehicleIdentityService.java rename to modules/testing/vehicle-identity-test-support/src/main/java/com/lingniu/ingest/identity/InMemoryVehicleIdentityService.java index f30866f6..b9d97bc3 100644 --- a/modules/inbound/inbound-mqtt/src/test/java/com/lingniu/ingest/identity/InMemoryVehicleIdentityService.java +++ b/modules/testing/vehicle-identity-test-support/src/main/java/com/lingniu/ingest/identity/InMemoryVehicleIdentityService.java @@ -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); } diff --git a/pom.xml b/pom.xml index bb95ea2a..464b70c6 100644 --- a/pom.xml +++ b/pom.xml @@ -23,6 +23,7 @@ modules/core/ingest-core modules/core/session-core modules/core/vehicle-identity + modules/testing/vehicle-identity-test-support modules/core/observability modules/sinks/sink-kafka modules/sinks/sink-archive @@ -201,6 +202,11 @@ vehicle-identity ${project.version} + + com.lingniu.ingest + vehicle-identity-test-support + ${project.version} + com.lingniu.ingest observability