fix(adr-115/test): per-test MQTT client_id so session-takeover doesn't break state test
The mqtt-integration test suite still failed `state_messages_published_
on_snapshot_broadcast` after the timing fix (5ed8e3451) — but with a
new symptom: 'expected ON state, got []'. The subscriber captured ZERO
messages on the presence state topic.
Root cause: all three integration tests built `client_id` as
`ruview-int-test-<pid>` — the same string for every test in the
sequential cargo-test run. MQTT brokers default to "session takeover":
when a new connect arrives with the same client_id as an existing
session, mosquitto disconnects the old one immediately.
Sequence on CI (`--test-threads=1`):
1. discovery_topics_appear_on_broker connects (ruview-int-test-1234)
2. test passes; publisher task continues running in background
3. privacy_mode_suppresses_biometric_discovery connects (same id)
→ mosquitto kicks test 1's publisher mid-rumqttc-disconnect-handshake
4. state_messages_published_on_snapshot_broadcast connects (same id)
→ mosquitto kicks test 2's publisher
→ test 3's publisher in turn races with the broker's cleanup
and its first publishes may land in a half-cleaned session
→ state messages dropped silently
Fix: include a per-test label in the client_id
(`ruview-int-test-<pid>-<label>` — labels: "discovery", "privacy",
"state"). Each test gets its own MQTT session; no cross-test takeover.
Refs PR #778, issue #776.
Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
parent
00e766ec28
commit
2aeed32a72
|
|
@ -58,13 +58,16 @@ fn should_run() -> Option<u16> {
|
||||||
Some(port)
|
Some(port)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_cfg(port: u16, privacy_mode: bool) -> std::sync::Arc<MqttConfig> {
|
fn make_cfg(port: u16, privacy_mode: bool, label: &str) -> std::sync::Arc<MqttConfig> {
|
||||||
std::sync::Arc::new(MqttConfig {
|
std::sync::Arc::new(MqttConfig {
|
||||||
host: "127.0.0.1".into(),
|
host: "127.0.0.1".into(),
|
||||||
port,
|
port,
|
||||||
username: None,
|
username: None,
|
||||||
password: None,
|
password: None,
|
||||||
client_id: format!("ruview-int-test-{}", std::process::id()),
|
// Per-test client_id so cargo test --test-threads=1 doesn't make
|
||||||
|
// mosquitto kick the previous session when the next test connects
|
||||||
|
// with the same client_id (default MQTT session-takeover behaviour).
|
||||||
|
client_id: format!("ruview-int-test-{}-{}", std::process::id(), label),
|
||||||
discovery_prefix: "homeassistant".into(),
|
discovery_prefix: "homeassistant".into(),
|
||||||
tls: TlsConfig::Off,
|
tls: TlsConfig::Off,
|
||||||
refresh_secs: 60,
|
refresh_secs: 60,
|
||||||
|
|
@ -139,7 +142,7 @@ async fn discovery_topics_appear_on_broker() {
|
||||||
subscribe_client(port, &["homeassistant/#"]).await;
|
subscribe_client(port, &["homeassistant/#"]).await;
|
||||||
|
|
||||||
// Spawn the publisher.
|
// Spawn the publisher.
|
||||||
let cfg = make_cfg(port, false);
|
let cfg = make_cfg(port, false, "discovery");
|
||||||
let builder = make_builder("inttest1");
|
let builder = make_builder("inttest1");
|
||||||
let (_tx, rx) = broadcast::channel::<VitalsSnapshot>(32);
|
let (_tx, rx) = broadcast::channel::<VitalsSnapshot>(32);
|
||||||
let _handle = spawn(cfg, builder, rx);
|
let _handle = spawn(cfg, builder, rx);
|
||||||
|
|
@ -189,7 +192,7 @@ async fn privacy_mode_suppresses_biometric_discovery() {
|
||||||
let (sub, mut sub_loop) =
|
let (sub, mut sub_loop) =
|
||||||
subscribe_client(port, &["homeassistant/#"]).await;
|
subscribe_client(port, &["homeassistant/#"]).await;
|
||||||
|
|
||||||
let cfg = make_cfg(port, /* privacy_mode = */ true);
|
let cfg = make_cfg(port, /* privacy_mode = */ true, "privacy");
|
||||||
let builder = make_builder("inttest2");
|
let builder = make_builder("inttest2");
|
||||||
let (_tx, rx) = broadcast::channel::<VitalsSnapshot>(32);
|
let (_tx, rx) = broadcast::channel::<VitalsSnapshot>(32);
|
||||||
let _handle = spawn(cfg, builder, rx);
|
let _handle = spawn(cfg, builder, rx);
|
||||||
|
|
@ -237,7 +240,7 @@ async fn state_messages_published_on_snapshot_broadcast() {
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
let cfg = make_cfg(port, false);
|
let cfg = make_cfg(port, false, "state");
|
||||||
let builder = make_builder("inttest3");
|
let builder = make_builder("inttest3");
|
||||||
let (tx, rx) = broadcast::channel::<VitalsSnapshot>(32);
|
let (tx, rx) = broadcast::channel::<VitalsSnapshot>(32);
|
||||||
let _handle = spawn(cfg, builder, rx);
|
let _handle = spawn(cfg, builder, rx);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue