blob: 335d4788bada3ad4d9faf6baa72554f6a2d2c43c [file]
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
"""
JMS Interoperability Tests - Star Configuration
Tests JMS message interoperability using a star topology centered on the
Qpid JMS Client. Every test pair includes the JMS client on at least one
side, validating that each AMQP client can correctly send to and receive
from a native JMS endpoint.
Star Pairs (11 total):
- JMS -> AMQP client (5 pairs)
- AMQP client -> JMS (5 pairs)
- JMS -> JMS (baseline)
Message Types: Incremental
- Phase 2b: TextMessage only
- Phase 2c: + BytesMessage, Message, MapMessage, StreamMessage
- Phase 2d: + Headers (JMSCorrelationID, JMSReplyTo, JMSType)
- Phase 2e: + Properties
"""
import json
import os
import subprocess
from pathlib import Path
from typing import Any
import pytest
from shim_registry import DISCOVERED_SHIMS, STAR_PAIRS
# =============================================================================
# Test Data
# =============================================================================
# TextMessage test values (Phase 2b - initial implementation)
TEXT_MESSAGE_VALUES = [
"", # Empty string
"Hello, world", # Simple ASCII
"Charlie's \"peach\"", # Quotes and apostrophe
"Unicode: ñ 日本語 🎉", # Unicode characters
"The quick brown fox jumped over the lazy dog.", # Longer text
]
# BytesMessage test values (Phase 2c.1 - hex-encoded binary data)
# Lengths chosen to avoid 1/2/4/8 bytes which JMS receiver reinterprets as typed values
BYTES_MESSAGE_VALUES = [
"", # Empty bytes
"48656c6c6f", # 5 bytes: "Hello" in ASCII
"000102fdfeff", # 6 bytes: boundary values including 0x00 and 0xff
]
# MapMessage test values (Phase 2c.2 - string values to avoid type ambiguity)
MAP_MESSAGE_VALUES = [
"Hello",
"world",
]
# StreamMessage test values (Phase 2c.2 - string values to avoid type ambiguity)
STREAM_MESSAGE_VALUES = [
"Hello",
"world",
]
# JMS Header test data (Phase 2d)
JMS_HEADERS_CORRELATION_ID_STRING = [
"Hello, world",
"correlation-123",
"Charlie's \"peach\"",
]
JMS_HEADERS_CORRELATION_ID_BYTES = [
"48656c6c6f", # "Hello"
"636f7272656c6174696f6e", # "correlation"
]
JMS_HEADERS_REPLY_TO_QUEUE = [
"reply-queue-1",
"reply-queue-2",
]
JMS_HEADERS_REPLY_TO_TOPIC = [
"reply-topic-1",
"reply-topic-2",
]
JMS_HEADERS_JMS_TYPE = [
"OrderRequest",
"OrderResponse",
"Hello, world",
]
# Phase 2e: JMS Application Properties test data
JMS_PROPS_BOOLEAN = {
"bool_true": {"type": "boolean", "value": True},
"bool_false": {"type": "boolean", "value": False},
}
JMS_PROPS_BYTE = {
"byte_pos": {"type": "byte", "value": "0x0f"},
"byte_neg": {"type": "byte", "value": "0xff"},
"byte_zero": {"type": "byte", "value": "0x00"},
}
JMS_PROPS_SHORT = {
"short_pos": {"type": "short", "value": "0x1234"},
"short_neg": {"type": "short", "value": "0xffff"},
"short_zero": {"type": "short", "value": "0x0000"},
}
JMS_PROPS_INT = {
"int_pos": {"type": "int", "value": "0x12345678"},
"int_neg": {"type": "int", "value": "0xffffffff"},
"int_zero": {"type": "int", "value": "0x00000000"},
}
JMS_PROPS_LONG = {
"long_pos": {"type": "long", "value": "0x0123456789abcdef"},
"long_neg": {"type": "long", "value": "0xffffffffffffffff"},
"long_zero": {"type": "long", "value": "0x0000000000000000"},
}
JMS_PROPS_FLOAT = {
"float_pi": {"type": "float", "value": "0x40490fdb"},
"float_neg": {"type": "float", "value": "0xc0490fdb"},
"float_zero": {"type": "float", "value": "0x00000000"},
}
JMS_PROPS_DOUBLE = {
"double_pi": {"type": "double", "value": "0x400921fb54442d18"},
"double_neg": {"type": "double", "value": "0xc00921fb54442d18"},
"double_zero": {"type": "double", "value": "0x0000000000000000"},
}
JMS_PROPS_STRING = {
"str_hello": {"type": "string", "value": "Hello, world"},
"str_special": {"type": "string", "value": "Charlie's \"peach\""},
"str_empty": {"type": "string", "value": ""},
}
# =============================================================================
# Fixtures
# =============================================================================
@pytest.fixture
def broker_url():
"""Get broker URL from environment or use default."""
return os.environ.get("QIT_BROKER_URL", "localhost:5672")
@pytest.fixture
def test_queue():
"""Generate unique queue name for test isolation."""
import random
import string
suffix = "".join(random.choices(string.ascii_lowercase + string.digits, k=8))
return f"qit.test.jms.{suffix}"
# =============================================================================
# Shim Runners
# =============================================================================
def run_sender(
client: str,
broker_url: str,
queue: str,
messages: list[dict[str, Any]],
project_root: Path,
amqp_type: str = "string",
jms_type: str = "JMS_TEXTMESSAGE_TYPE",
headers: dict[str, Any] | None = None,
properties: dict[str, Any] | None = None,
) -> dict[str, Any]:
"""Run sender shim for any client."""
shim = DISCOVERED_SHIMS[client]
broker = shim.broker_prefix + broker_url
if shim.shim_type == "jms":
cmd = [
str(shim.shim_dir / "shim.sh"), "send",
"--broker", broker_url,
"--queue", queue,
"--type", jms_type,
"--data", json.dumps(messages),
]
else:
cmd = [
str(shim.shim_dir / "shim.sh"), "send",
"--broker", broker,
"--queue", queue,
"--type", amqp_type,
"--count", str(len(messages)),
"--data", json.dumps(messages),
"--jms-mode",
]
if headers:
cmd.extend(["--headers", json.dumps(headers)])
if properties:
cmd.extend(["--properties", json.dumps(properties)])
result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
if result.returncode != 0:
pytest.fail(f"{shim.name} sender failed: {result.stderr}")
return json.loads(result.stdout)
def run_receiver(
client: str,
broker_url: str,
queue: str,
count: int,
project_root: Path,
timeout: int = 30,
) -> dict[str, Any]:
"""Run receiver shim for any client."""
shim = DISCOVERED_SHIMS[client]
broker = shim.broker_prefix + broker_url
cmd = [
str(shim.shim_dir / "shim.sh"), "receive",
"--broker", broker,
"--queue", queue,
"--count", str(count),
"--timeout", str(timeout),
]
result = subprocess.run(cmd, capture_output=True, text=True, timeout=timeout + 10)
if result.returncode != 0:
pytest.fail(f"{shim.name} receiver failed: {result.stderr}")
return json.loads(result.stdout)
# =============================================================================
# Test Helpers
# =============================================================================
def normalize_message_type(msg_type: str) -> str:
"""Normalize message type for comparison across JMS and AMQP clients."""
if msg_type in ("string", "text"):
return "text"
if msg_type in ("binary", "bytes"):
return "bytes"
if msg_type in ("null", "none"):
return "none"
return msg_type
def normalize_value(msg_type: str, value: Any) -> Any:
"""Normalize message value for comparison."""
normalized_type = normalize_message_type(msg_type)
if normalized_type == "bytes" and isinstance(value, str):
return value.lower()
return value
def compare_messages(sent: list[dict], received: list[dict], sender: str, receiver: str) -> None:
"""Compare sent and received messages."""
if len(sent) != len(received):
pytest.fail(
f"{sender}→{receiver}: Message count mismatch - "
f"sent {len(sent)}, received {len(received)}"
)
for i, (s, r) in enumerate(zip(sent, received)):
sent_type = normalize_message_type(s["type"])
recv_type = normalize_message_type(r["type"])
assert sent_type == recv_type, (
f"{sender}→{receiver}: Message {i} type mismatch - "
f"sent {s['type']}, received {r['type']}"
)
sent_value = normalize_value(s["type"], s.get("value"))
recv_value = normalize_value(r["type"], r.get("value"))
assert sent_value == recv_value, (
f"{sender}→{receiver}: Message {i} value mismatch - "
f"sent {repr(s['value'])}, received {repr(r['value'])}"
)
# =============================================================================
# Test Matrix
# =============================================================================
@pytest.mark.parametrize("sender_client,receiver_client", STAR_PAIRS)
@pytest.mark.parametrize("text_value", TEXT_MESSAGE_VALUES)
def test_jms_textmessage_interop(
sender_client: str,
receiver_client: str,
text_value: str,
broker_url: str,
test_queue: str,
project_root: Path,
):
"""
Test JMS TextMessage interoperability using star configuration.
The JMS client (Qpid JMS) is always on at least one side of every pair.
This validates that each AMQP client can correctly send JMS-annotated
messages to, and receive JMS messages from, the native JMS client.
"""
sender_shim = DISCOVERED_SHIMS[sender_client]
if sender_shim.shim_type == "jms":
messages = [{"index": 0, "type": "text", "value": text_value}]
else:
messages = [{"index": 0, "type": "string", "value": text_value}]
send_result = run_sender(sender_client, broker_url, test_queue, messages, project_root)
recv_result = run_receiver(receiver_client, broker_url, test_queue, len(messages), project_root)
received = recv_result["messages"]
compare_messages(messages, received, sender_client, receiver_client)
@pytest.mark.parametrize("sender_client,receiver_client", STAR_PAIRS)
@pytest.mark.parametrize("bytes_value", BYTES_MESSAGE_VALUES)
def test_jms_bytesmessage_interop(
sender_client: str,
receiver_client: str,
bytes_value: str,
broker_url: str,
test_queue: str,
project_root: Path,
):
"""Test JMS BytesMessage interoperability using star configuration."""
sender_shim = DISCOVERED_SHIMS[sender_client]
if sender_shim.shim_type == "jms":
messages = [{"index": 0, "type": "bytes", "value": bytes_value}]
else:
messages = [{"index": 0, "type": "binary", "value": bytes_value}]
send_result = run_sender(
sender_client, broker_url, test_queue, messages, project_root,
amqp_type="binary", jms_type="JMS_BYTESMESSAGE_TYPE",
)
recv_result = run_receiver(receiver_client, broker_url, test_queue, len(messages), project_root)
received = recv_result["messages"]
compare_messages(messages, received, sender_client, receiver_client)
@pytest.mark.parametrize("sender_client,receiver_client", STAR_PAIRS)
def test_jms_message_interop(
sender_client: str,
receiver_client: str,
broker_url: str,
test_queue: str,
project_root: Path,
):
"""Test JMS Message (empty/no body) interoperability using star configuration."""
if sender_client == "javascript-rhea" and DISCOVERED_SHIMS[receiver_client].shim_type == "jms":
pytest.xfail("Rhea sends AmqpValue(null) for empty body, JMS maps this to TextMessage")
sender_shim = DISCOVERED_SHIMS[sender_client]
if sender_shim.shim_type == "jms":
messages = [{"index": 0, "type": "none", "value": None}]
else:
messages = [{"index": 0, "type": "null", "value": None}]
send_result = run_sender(
sender_client, broker_url, test_queue, messages, project_root,
amqp_type="null", jms_type="JMS_MESSAGE_TYPE",
)
recv_result = run_receiver(receiver_client, broker_url, test_queue, len(messages), project_root)
received = recv_result["messages"]
compare_messages(messages, received, sender_client, receiver_client)
@pytest.mark.parametrize("sender_client,receiver_client", STAR_PAIRS)
@pytest.mark.parametrize("map_value", MAP_MESSAGE_VALUES)
def test_jms_mapmessage_interop(
sender_client: str,
receiver_client: str,
map_value: str,
broker_url: str,
test_queue: str,
project_root: Path,
):
"""Test JMS MapMessage interoperability using star configuration."""
messages = [{"index": 0, "type": "string", "value": map_value}]
send_result = run_sender(
sender_client, broker_url, test_queue, messages, project_root,
amqp_type="map", jms_type="JMS_MAPMESSAGE_TYPE",
)
recv_result = run_receiver(receiver_client, broker_url, test_queue, len(messages), project_root)
received = recv_result["messages"]
compare_messages(messages, received, sender_client, receiver_client)
@pytest.mark.parametrize("sender_client,receiver_client", STAR_PAIRS)
@pytest.mark.parametrize("stream_value", STREAM_MESSAGE_VALUES)
def test_jms_streammessage_interop(
sender_client: str,
receiver_client: str,
stream_value: str,
broker_url: str,
test_queue: str,
project_root: Path,
):
"""Test JMS StreamMessage interoperability using star configuration."""
messages = [{"index": 0, "type": "string", "value": stream_value}]
send_result = run_sender(
sender_client, broker_url, test_queue, messages, project_root,
amqp_type="list", jms_type="JMS_STREAMMESSAGE_TYPE",
)
recv_result = run_receiver(receiver_client, broker_url, test_queue, len(messages), project_root)
received = recv_result["messages"]
compare_messages(messages, received, sender_client, receiver_client)
# =============================================================================
# Phase 2d: JMS Headers
# =============================================================================
def compare_headers(
sent_headers: dict[str, Any],
received_headers: dict[str, Any],
sender: str,
receiver: str,
) -> None:
"""Compare sent and received JMS headers."""
for header_name, sent_value in sent_headers.items():
assert header_name in received_headers, (
f"{sender}→{receiver}: Missing header {header_name} "
f"in received: {received_headers}"
)
recv_value = received_headers[header_name]
if header_name == "JMSCorrelationID":
if sent_value.get("type") == "bytes":
if isinstance(recv_value, dict):
assert recv_value.get("type") == "bytes", (
f"Expected bytes correlation ID, got {recv_value}"
)
assert recv_value["value"].lower() == sent_value["value"].lower()
else:
pytest.fail(f"Expected bytes correlation ID, got string: {recv_value}")
else:
expected_str = sent_value["value"]
if isinstance(recv_value, str):
assert recv_value == expected_str
elif isinstance(recv_value, dict) and recv_value.get("type") == "bytes":
expected_hex = expected_str.encode("utf-8").hex()
assert recv_value["value"].lower() == expected_hex.lower()
else:
pytest.fail(f"Unexpected correlation ID format: {recv_value}")
elif header_name == "JMSReplyTo":
assert isinstance(recv_value, dict), f"JMSReplyTo should be dict, got {recv_value}"
assert recv_value.get("type") == sent_value.get("type"), (
f"JMSReplyTo type mismatch: sent {sent_value.get('type')}, got {recv_value.get('type')}"
)
assert recv_value.get("value") == sent_value.get("value"), (
f"JMSReplyTo value mismatch: sent {sent_value.get('value')}, got {recv_value.get('value')}"
)
elif header_name == "JMSType":
expected = sent_value["value"] if isinstance(sent_value, dict) else sent_value
assert recv_value == expected, (
f"JMSType mismatch: sent {expected}, got {recv_value}"
)
def _header_test_message(sender_client: str) -> list[dict[str, Any]]:
"""Create a single TextMessage for header tests."""
sender_shim = DISCOVERED_SHIMS[sender_client]
if sender_shim.shim_type == "jms":
return [{"index": 0, "type": "text", "value": "header-test"}]
return [{"index": 0, "type": "string", "value": "header-test"}]
@pytest.mark.parametrize("sender_client,receiver_client", STAR_PAIRS)
@pytest.mark.parametrize("corr_id", JMS_HEADERS_CORRELATION_ID_STRING)
def test_jms_header_correlationid_string(
sender_client: str,
receiver_client: str,
corr_id: str,
broker_url: str,
test_queue: str,
project_root: Path,
):
"""Test JMSCorrelationID header with string values."""
headers = {"JMSCorrelationID": {"type": "string", "value": corr_id}}
messages = _header_test_message(sender_client)
run_sender(
sender_client, broker_url, test_queue, messages, project_root,
headers=headers,
)
recv_result = run_receiver(receiver_client, broker_url, test_queue, 1, project_root)
received = recv_result["messages"]
assert len(received) == 1
assert "headers" in received[0], f"No headers in received message: {received[0]}"
compare_headers(headers, received[0]["headers"], sender_client, receiver_client)
@pytest.mark.parametrize("sender_client,receiver_client", STAR_PAIRS)
@pytest.mark.parametrize("corr_id_hex", JMS_HEADERS_CORRELATION_ID_BYTES)
def test_jms_header_correlationid_bytes(
sender_client: str,
receiver_client: str,
corr_id_hex: str,
broker_url: str,
test_queue: str,
project_root: Path,
):
"""Test JMSCorrelationID header with binary values."""
if sender_client in ("dotnet-proton", "java-protonj2"):
pytest.xfail(f"{sender_client} client cannot send binary correlation IDs (message-id type restriction)")
if receiver_client == "java-protonj2":
pytest.xfail("ProtonJ2 decodes binary correlation IDs as UTF-8 strings")
headers = {"JMSCorrelationID": {"type": "bytes", "value": corr_id_hex}}
messages = _header_test_message(sender_client)
run_sender(
sender_client, broker_url, test_queue, messages, project_root,
headers=headers,
)
recv_result = run_receiver(receiver_client, broker_url, test_queue, 1, project_root)
received = recv_result["messages"]
assert len(received) == 1
assert "headers" in received[0], f"No headers in received message: {received[0]}"
compare_headers(headers, received[0]["headers"], sender_client, receiver_client)
@pytest.mark.parametrize("sender_client,receiver_client", STAR_PAIRS)
@pytest.mark.parametrize("reply_queue", JMS_HEADERS_REPLY_TO_QUEUE)
def test_jms_header_replyto_queue(
sender_client: str,
receiver_client: str,
reply_queue: str,
broker_url: str,
test_queue: str,
project_root: Path,
):
"""Test JMSReplyTo header with queue destination."""
headers = {"JMSReplyTo": {"type": "queue", "value": reply_queue}}
messages = _header_test_message(sender_client)
run_sender(
sender_client, broker_url, test_queue, messages, project_root,
headers=headers,
)
recv_result = run_receiver(receiver_client, broker_url, test_queue, 1, project_root)
received = recv_result["messages"]
assert len(received) == 1
assert "headers" in received[0], f"No headers in received message: {received[0]}"
compare_headers(headers, received[0]["headers"], sender_client, receiver_client)
@pytest.mark.parametrize("sender_client,receiver_client", STAR_PAIRS)
@pytest.mark.parametrize("reply_topic", JMS_HEADERS_REPLY_TO_TOPIC)
def test_jms_header_replyto_topic(
sender_client: str,
receiver_client: str,
reply_topic: str,
broker_url: str,
test_queue: str,
project_root: Path,
):
"""Test JMSReplyTo header with topic destination."""
headers = {"JMSReplyTo": {"type": "topic", "value": reply_topic}}
messages = _header_test_message(sender_client)
run_sender(
sender_client, broker_url, test_queue, messages, project_root,
headers=headers,
)
recv_result = run_receiver(receiver_client, broker_url, test_queue, 1, project_root)
received = recv_result["messages"]
assert len(received) == 1
assert "headers" in received[0], f"No headers in received message: {received[0]}"
compare_headers(headers, received[0]["headers"], sender_client, receiver_client)
@pytest.mark.parametrize("sender_client,receiver_client", STAR_PAIRS)
@pytest.mark.parametrize("jms_type_value", JMS_HEADERS_JMS_TYPE)
def test_jms_header_jmstype(
sender_client: str,
receiver_client: str,
jms_type_value: str,
broker_url: str,
test_queue: str,
project_root: Path,
):
"""Test JMSType header."""
headers = {"JMSType": {"type": "string", "value": jms_type_value}}
messages = _header_test_message(sender_client)
run_sender(
sender_client, broker_url, test_queue, messages, project_root,
headers=headers,
)
recv_result = run_receiver(receiver_client, broker_url, test_queue, 1, project_root)
received = recv_result["messages"]
assert len(received) == 1
assert "headers" in received[0], f"No headers in received message: {received[0]}"
compare_headers(headers, received[0]["headers"], sender_client, receiver_client)
# =============================================================================
# Phase 2e: JMS Application Properties
# =============================================================================
def compare_properties(
sent_props: dict[str, Any],
received_props: dict[str, Any],
sender: str,
receiver: str,
) -> None:
"""Compare sent and received JMS application properties."""
for prop_name, sent_obj in sent_props.items():
assert prop_name in received_props, (
f"{sender}→{receiver}: Missing property '{prop_name}' "
f"in received: {received_props}"
)
recv_obj = received_props[prop_name]
assert isinstance(recv_obj, dict), (
f"{sender}→{receiver}: Property '{prop_name}' should be dict, got {recv_obj}"
)
assert recv_obj["type"] == sent_obj["type"], (
f"{sender}→{receiver}: Property '{prop_name}' type mismatch: "
f"sent {sent_obj['type']}, got {recv_obj['type']}"
)
if sent_obj["type"] == "boolean":
assert recv_obj["value"] == sent_obj["value"], (
f"{sender}→{receiver}: Property '{prop_name}' value mismatch: "
f"sent {sent_obj['value']}, got {recv_obj['value']}"
)
elif sent_obj["type"] == "string":
assert recv_obj["value"] == sent_obj["value"], (
f"{sender}→{receiver}: Property '{prop_name}' value mismatch: "
f"sent {sent_obj['value']!r}, got {recv_obj['value']!r}"
)
else:
assert recv_obj["value"].lower() == sent_obj["value"].lower(), (
f"{sender}→{receiver}: Property '{prop_name}' value mismatch: "
f"sent {sent_obj['value']}, got {recv_obj['value']}"
)
@pytest.mark.parametrize("sender_client,receiver_client", STAR_PAIRS)
def test_jms_property_boolean(
sender_client: str,
receiver_client: str,
broker_url: str,
test_queue: str,
project_root: Path,
) -> None:
"""Test JMS boolean application properties round-trip."""
messages = _header_test_message(sender_client)
run_sender(
sender_client, broker_url, test_queue, messages, project_root,
properties=JMS_PROPS_BOOLEAN,
)
recv_result = run_receiver(receiver_client, broker_url, test_queue, 1, project_root)
received = recv_result["messages"]
assert len(received) == 1
assert "properties" in received[0], f"No properties in received message: {received[0]}"
compare_properties(JMS_PROPS_BOOLEAN, received[0]["properties"], sender_client, receiver_client)
@pytest.mark.parametrize("sender_client,receiver_client", STAR_PAIRS)
def test_jms_property_byte(
sender_client: str,
receiver_client: str,
broker_url: str,
test_queue: str,
project_root: Path,
) -> None:
"""Test JMS byte application properties round-trip."""
if receiver_client == "javascript-rhea" and sender_client != "javascript-rhea":
pytest.xfail("Rhea loses AMQP byte type — JS has no typed integers")
messages = _header_test_message(sender_client)
run_sender(
sender_client, broker_url, test_queue, messages, project_root,
properties=JMS_PROPS_BYTE,
)
recv_result = run_receiver(receiver_client, broker_url, test_queue, 1, project_root)
received = recv_result["messages"]
assert len(received) == 1
assert "properties" in received[0], f"No properties in received message: {received[0]}"
compare_properties(JMS_PROPS_BYTE, received[0]["properties"], sender_client, receiver_client)
@pytest.mark.parametrize("sender_client,receiver_client", STAR_PAIRS)
def test_jms_property_short(
sender_client: str,
receiver_client: str,
broker_url: str,
test_queue: str,
project_root: Path,
) -> None:
"""Test JMS short application properties round-trip."""
if receiver_client == "javascript-rhea" and sender_client != "javascript-rhea":
pytest.xfail("Rhea loses AMQP short type — JS has no typed integers")
messages = _header_test_message(sender_client)
run_sender(
sender_client, broker_url, test_queue, messages, project_root,
properties=JMS_PROPS_SHORT,
)
recv_result = run_receiver(receiver_client, broker_url, test_queue, 1, project_root)
received = recv_result["messages"]
assert len(received) == 1
assert "properties" in received[0], f"No properties in received message: {received[0]}"
compare_properties(JMS_PROPS_SHORT, received[0]["properties"], sender_client, receiver_client)
@pytest.mark.parametrize("sender_client,receiver_client", STAR_PAIRS)
def test_jms_property_int(
sender_client: str,
receiver_client: str,
broker_url: str,
test_queue: str,
project_root: Path,
) -> None:
"""Test JMS int application properties round-trip."""
if receiver_client == "javascript-rhea" and sender_client != "javascript-rhea":
pytest.xfail("Rhea loses AMQP int type — JS has no typed integers")
messages = _header_test_message(sender_client)
run_sender(
sender_client, broker_url, test_queue, messages, project_root,
properties=JMS_PROPS_INT,
)
recv_result = run_receiver(receiver_client, broker_url, test_queue, 1, project_root)
received = recv_result["messages"]
assert len(received) == 1
assert "properties" in received[0], f"No properties in received message: {received[0]}"
compare_properties(JMS_PROPS_INT, received[0]["properties"], sender_client, receiver_client)
@pytest.mark.parametrize("sender_client,receiver_client", STAR_PAIRS)
def test_jms_property_long(
sender_client: str,
receiver_client: str,
broker_url: str,
test_queue: str,
project_root: Path,
) -> None:
"""Test JMS long application properties round-trip."""
if receiver_client == "javascript-rhea" and sender_client != "javascript-rhea":
pytest.xfail("Rhea loses AMQP long type — JS number can't represent 64-bit integers")
messages = _header_test_message(sender_client)
run_sender(
sender_client, broker_url, test_queue, messages, project_root,
properties=JMS_PROPS_LONG,
)
recv_result = run_receiver(receiver_client, broker_url, test_queue, 1, project_root)
received = recv_result["messages"]
assert len(received) == 1
assert "properties" in received[0], f"No properties in received message: {received[0]}"
compare_properties(JMS_PROPS_LONG, received[0]["properties"], sender_client, receiver_client)
@pytest.mark.parametrize("sender_client,receiver_client", STAR_PAIRS)
def test_jms_property_float(
sender_client: str,
receiver_client: str,
broker_url: str,
test_queue: str,
project_root: Path,
) -> None:
"""Test JMS float application properties round-trip."""
if receiver_client == "javascript-rhea" and sender_client != "javascript-rhea":
pytest.xfail("Rhea loses AMQP float type — JS has only double-precision numbers")
messages = _header_test_message(sender_client)
run_sender(
sender_client, broker_url, test_queue, messages, project_root,
properties=JMS_PROPS_FLOAT,
)
recv_result = run_receiver(receiver_client, broker_url, test_queue, 1, project_root)
received = recv_result["messages"]
assert len(received) == 1
assert "properties" in received[0], f"No properties in received message: {received[0]}"
compare_properties(JMS_PROPS_FLOAT, received[0]["properties"], sender_client, receiver_client)
@pytest.mark.parametrize("sender_client,receiver_client", STAR_PAIRS)
def test_jms_property_double(
sender_client: str,
receiver_client: str,
broker_url: str,
test_queue: str,
project_root: Path,
) -> None:
"""Test JMS double application properties round-trip."""
messages = _header_test_message(sender_client)
run_sender(
sender_client, broker_url, test_queue, messages, project_root,
properties=JMS_PROPS_DOUBLE,
)
recv_result = run_receiver(receiver_client, broker_url, test_queue, 1, project_root)
received = recv_result["messages"]
assert len(received) == 1
assert "properties" in received[0], f"No properties in received message: {received[0]}"
compare_properties(JMS_PROPS_DOUBLE, received[0]["properties"], sender_client, receiver_client)
@pytest.mark.parametrize("sender_client,receiver_client", STAR_PAIRS)
def test_jms_property_string(
sender_client: str,
receiver_client: str,
broker_url: str,
test_queue: str,
project_root: Path,
) -> None:
"""Test JMS string application properties round-trip."""
messages = _header_test_message(sender_client)
run_sender(
sender_client, broker_url, test_queue, messages, project_root,
properties=JMS_PROPS_STRING,
)
recv_result = run_receiver(receiver_client, broker_url, test_queue, 1, project_root)
received = recv_result["messages"]
assert len(received) == 1
assert "properties" in received[0], f"No properties in received message: {received[0]}"
compare_properties(JMS_PROPS_STRING, received[0]["properties"], sender_client, receiver_client)