test: carbon-copied REST test uses same-bare-JID second resource
The test was skipping because it depended on the second_client fixture, which uses XMPP_JID2 (a distinct account). Carbons require both resources to share the same bare JID. Rewrite to create a second VNCXmppClient inline with the same bare JID as xmpp_client but a different resource (/carbon-<random>), so the test runs regardless of whether XMPP_JID2 is configured or distinct. Part-of: <http://gitlab.vnc.biz/uxf/vnctalk-prosody/-/merge_requests/3>
This commit is contained in:
+64
-35
@@ -6,6 +6,8 @@ import pytest
|
||||
import slixmpp
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
from conftest import VNCXmppClient
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
class TestCoreXmpp:
|
||||
@@ -235,47 +237,74 @@ class TestRestToCarbonsRoundtrip:
|
||||
"""Priority 2 from AUDIT: REST-injected messages are carbon-copied."""
|
||||
|
||||
async def test_rest_message_carbon_copied_to_second_resource(
|
||||
self, xmpp_client, second_client, xmpp_config, rest_injector
|
||||
self, xmpp_client, xmpp_config, rest_injector
|
||||
):
|
||||
"""Enable carbons on both resources. Inject via REST. Second resource must receive a carbon."""
|
||||
# Both clients share the same bare JID (second_client is same account, different resource)
|
||||
# or they may be different accounts. For carbons, they MUST be same bare JID.
|
||||
if xmpp_client.boundjid.bare != second_client.boundjid.bare:
|
||||
pytest.skip("Carbons test requires both clients to share the same bare JID")
|
||||
"""Enable carbons on two resources of the same account. Inject via REST.
|
||||
Second resource must receive a carbon copy.
|
||||
|
||||
await xmpp_client.enable_carbons()
|
||||
await second_client.enable_carbons()
|
||||
await asyncio.sleep(0.5)
|
||||
Creates a second client with the same bare JID as xmpp_client but a
|
||||
different resource, so this test works even when XMPP_JID2 is a
|
||||
distinct account (or not configured at all).
|
||||
"""
|
||||
bare_jid = xmpp_client.boundjid.bare
|
||||
password = xmpp_config["password"]
|
||||
second_jid = f"{bare_jid}/carbon-{uuid.uuid4().hex[:4]}"
|
||||
|
||||
carbon_received = asyncio.Event()
|
||||
carbon_bodies = []
|
||||
|
||||
def on_message(msg):
|
||||
if msg["type"] == "chat":
|
||||
carb = msg.xml.find("{urn:xmpp:carbons:2}received")
|
||||
if carb is not None:
|
||||
fwd = carb.find("{urn:xmpp:forward:0}forwarded")
|
||||
if fwd is not None:
|
||||
body_el = fwd.find("{jabber:client}message/{jabber:client}body")
|
||||
if body_el is not None and body_el.text:
|
||||
carbon_bodies.append(body_el.text)
|
||||
carbon_received.set()
|
||||
|
||||
second_client.add_event_handler("message", on_message)
|
||||
second_client = VNCXmppClient(
|
||||
second_jid, password,
|
||||
host=xmpp_config["host"], port=xmpp_config["port"],
|
||||
use_ssl=True, verify_ssl=xmpp_config["verify_ssl"],
|
||||
)
|
||||
try:
|
||||
msg_id = f"rest-carbons-{uuid.uuid4().hex[:12]}"
|
||||
from_jid = xmpp_client.boundjid.bare
|
||||
to_jid = xmpp_client.boundjid.bare
|
||||
body = f"carbon test {msg_id}"
|
||||
await second_client.async_connect(timeout=30)
|
||||
|
||||
status, _ = await rest_injector.inject_message(msg_id, from_jid, to_jid, body)
|
||||
assert status in (201, 422)
|
||||
await xmpp_client.enable_carbons()
|
||||
await second_client.enable_carbons()
|
||||
await asyncio.sleep(0.5)
|
||||
|
||||
carbon_received = asyncio.Event()
|
||||
carbon_bodies = []
|
||||
|
||||
# A REST-injected message enters through the sender-side (c2s)
|
||||
# carbons path (the mod_carbons patch hooks vnc-rest-message as a
|
||||
# c2s handler), so other resources of the *sender* receive <sent>
|
||||
# carbons; <received> would only appear on recipient resources.
|
||||
# slixmpp's "message" event only fires for messages with a <body>;
|
||||
# carbon wrappers have none, so a raw stream handler is needed.
|
||||
from slixmpp.xmlstream.handler import Callback
|
||||
from slixmpp.xmlstream.matcher import MatchXPath
|
||||
|
||||
def on_carbon_wrapper(msg):
|
||||
for tag in ("sent", "received"):
|
||||
carb = msg.xml.find("{urn:xmpp:carbons:2}" + tag)
|
||||
if carb is not None:
|
||||
fwd = carb.find("{urn:xmpp:forward:0}forwarded")
|
||||
if fwd is not None:
|
||||
body_el = fwd.find("{jabber:client}message/{jabber:client}body")
|
||||
if body_el is not None and body_el.text:
|
||||
carbon_bodies.append(body_el.text)
|
||||
carbon_received.set()
|
||||
|
||||
second_client.register_handler(Callback(
|
||||
"carbon-probe", MatchXPath("{jabber:client}message"), on_carbon_wrapper
|
||||
))
|
||||
try:
|
||||
await asyncio.wait_for(carbon_received.wait(), timeout=8)
|
||||
except asyncio.TimeoutError:
|
||||
pytest.fail("Carbon copy not received on second resource after REST injection")
|
||||
msg_id = f"rest-carbons-{uuid.uuid4().hex[:12]}"
|
||||
from_jid = bare_jid
|
||||
to_jid = bare_jid
|
||||
body = f"carbon test {msg_id}"
|
||||
|
||||
assert any(body in b for b in carbon_bodies), "Carbon body does not match injected message"
|
||||
status, _ = await rest_injector.inject_message(msg_id, from_jid, to_jid, body)
|
||||
assert status in (201, 422)
|
||||
|
||||
try:
|
||||
await asyncio.wait_for(carbon_received.wait(), timeout=8)
|
||||
except asyncio.TimeoutError:
|
||||
pytest.fail("Carbon copy not received on second resource after REST injection")
|
||||
|
||||
assert any(body in b for b in carbon_bodies), "Carbon body does not match injected message"
|
||||
finally:
|
||||
second_client.remove_handler("carbon-probe")
|
||||
finally:
|
||||
second_client.del_event_handler("message", on_message)
|
||||
if second_client.session_started_event.is_set():
|
||||
await second_client.async_disconnect()
|
||||
|
||||
Reference in New Issue
Block a user