Summary
The MQTT-over-TLS test skip-guard decides whether to run based on "a CA file exists
on disk", not "the CA can actually verify the broker". When a stale
$TMPDIR/tina4-mqtt-infra/certs/ca.crt is left over from an earlier
mqtt-infra.sh run, the guard finds it, declines to skip, and the tests then fail on
a certificate mismatch against whatever broker is currently listening on 8883.
Result: 6 red tests in EVERY framework, from an environment problem, with an error
message that looks like a code regression.
Evidence
Stale CA on disk (written 9 hours before the run):
/var/folders/.../T/tina4-mqtt-infra/certs/ca.crt Jul 23 19:12
It does not verify the live broker:
openssl s_client -connect 127.0.0.1:8883 -CAfile <that ca.crt>
subject=CN=localhost
issuer=CN=tina4-test-ca
Verify return code: 19 (self-signed certificate in certificate chain)
Full-suite impact, all four frameworks, same feature, same OpenSSL error:
| framework |
passed |
failed |
failing file |
| Python |
3642 |
6 |
tests/test_mqtt_auth_tls.py |
| PHP |
3959 |
6 errors |
MqttAuthTlsTest |
| Ruby |
4099 |
6 |
spec/mqtt_auth_tls_spec.rb |
| Node |
5663 |
1 file |
mqttAuthTls.test |
Proof it is the CA and not the code
Move the stale CA aside and re-run the same file:
7 passed, 10 skipped, 0 failed
The guard then fires exactly as designed. Restoring the file reproduces the 6
failures.
Root cause
In tests/test_mqtt_auth_tls.py (and the PHP/Ruby/Node equivalents) _ca_file()
falls back to the default mqtt-infra.sh cert path and returns it whenever the file
merely EXISTS:
default = os.path.join(TMPDIR, "tina4-mqtt-infra", "certs", "ca.crt")
return os.path.abspath(default) if os.path.isfile(default) else None
tls_broker = skipif(not _reachable(TLS_URL) or not CA, ...) therefore evaluates to
"do not skip" for a CA that cannot verify anything.
Proposed fix (all 4, parity)
Make the guard verify rather than merely locate: attempt a real TLS handshake (or an
SSLContext.load_verify_locations + connect) against the broker with that CA during
guard evaluation, and skip when it does not validate. A CA that cannot verify the
broker is functionally the same as no CA, and should skip with a clear reason
("CA present but does not verify the broker on 8883 -- re-run mqtt-infra.sh").
This is self-healing: a stale cert directory then produces skips with an actionable
message instead of six misleading failures.
Not yet fixed.
Summary
The MQTT-over-TLS test skip-guard decides whether to run based on "a CA file exists
on disk", not "the CA can actually verify the broker". When a stale
$TMPDIR/tina4-mqtt-infra/certs/ca.crtis left over from an earliermqtt-infra.shrun, the guard finds it, declines to skip, and the tests then fail ona certificate mismatch against whatever broker is currently listening on 8883.
Result: 6 red tests in EVERY framework, from an environment problem, with an error
message that looks like a code regression.
Evidence
Stale CA on disk (written 9 hours before the run):
It does not verify the live broker:
Full-suite impact, all four frameworks, same feature, same OpenSSL error:
tests/test_mqtt_auth_tls.pyMqttAuthTlsTestspec/mqtt_auth_tls_spec.rbmqttAuthTls.testProof it is the CA and not the code
Move the stale CA aside and re-run the same file:
The guard then fires exactly as designed. Restoring the file reproduces the 6
failures.
Root cause
In
tests/test_mqtt_auth_tls.py(and the PHP/Ruby/Node equivalents)_ca_file()falls back to the default
mqtt-infra.shcert path and returns it whenever the filemerely EXISTS:
tls_broker = skipif(not _reachable(TLS_URL) or not CA, ...)therefore evaluates to"do not skip" for a CA that cannot verify anything.
Proposed fix (all 4, parity)
Make the guard verify rather than merely locate: attempt a real TLS handshake (or an
SSLContext.load_verify_locations+ connect) against the broker with that CA duringguard evaluation, and skip when it does not validate. A CA that cannot verify the
broker is functionally the same as no CA, and should skip with a clear reason
("CA present but does not verify the broker on 8883 -- re-run mqtt-infra.sh").
This is self-healing: a stale cert directory then produces skips with an actionable
message instead of six misleading failures.
Not yet fixed.