test_: Code Migration from status-cli-tests for 1 on 1 message (#6022)

* test_: Code Migration from status-cli-tests 1_1 message

test_: Code Migration from status-cli-tests 1_1 message

test_: Code Migration from status-cli-tests addressing review comments

test_: Code Migration from status-cli-tests 1_1 message rebase

* test_: Code Migration from status-cli-tests for 1 on 1 message and added event validation

* test_: Code Migration from status-cli-tests for 1 on 1 logger fix
This commit is contained in:
shashank sanket 2024-11-03 16:26:33 +05:30 committed by Florin Barbu
parent 8c1d6b190a
commit 386a772e0d
No known key found for this signature in database
GPG Key ID: 593D6DBC6D9E5095
6 changed files with 193 additions and 10 deletions

View File

@ -47,5 +47,6 @@ PACKET_LOSS_CMD = "sudo tc qdisc add dev eth0 root netem loss 50%"
LOW_BANDWIDTH_CMD = "sudo tc qdisc add dev eth0 root tbf rate 1kbit burst 1kbit"
REMOVE_TC_CMD = "sudo tc qdisc del dev eth0 root"
NUM_CONTACT_REQUESTS = int(os.getenv("NUM_CONTACT_REQUESTS", "5"))
NUM_MESSAGES = int(os.getenv("NUM_MESSAGES", "25"))
NUM_MESSAGES = int(os.getenv("NUM_MESSAGES", "20"))
DELAY_BETWEEN_MESSAGES = int(os.getenv("NUM_MESSAGES", "1"))
EVENT_SIGNAL_TIMEOUT_SEC = int(os.getenv("EVENT_SIGNAL_TIMEOUT_SEC", "4"))

View File

@ -81,7 +81,7 @@ class StatusNode:
def start_signal_client(self):
ws_url = f"ws://localhost:{self.port}"
await_signals = ["history.request.started", "messages.new", "history.request.completed"]
await_signals = ["history.request.started", "messages.new", "message.delivered", "history.request.completed"]
self.signal_client = SignalClient(ws_url, await_signals)
websocket_thread = threading.Thread(target=self.signal_client._connect)

View File

@ -12,7 +12,7 @@ logger = get_custom_logger(__name__)
class TestContactRequest(StepsCommon):
def test_contact_request_baseline(self):
timeout_secs = 3
timeout_secs = 5
num_contact_requests = NUM_CONTACT_REQUESTS
project_root = get_project_root()
nodes = []

View File

@ -0,0 +1,114 @@
from uuid import uuid4
import pytest
from constants import *
from src.libs.common import delay
from src.libs.custom_logger import get_custom_logger
from src.steps.common import StepsCommon
from validators.message_validator import MessageValidator
logger = get_custom_logger(__name__)
@pytest.mark.usefixtures("start_2_nodes")
class TestOneToOneMessages(StepsCommon):
def test_one_to_one_message_baseline(self):
timeout_secs = EVENT_SIGNAL_TIMEOUT_SEC
num_messages = NUM_MESSAGES
nodes = [
(self.first_node, self.second_node, "second_node_user"),
(self.second_node, self.first_node, "first_node_user")
]
messages = []
self.accept_contact_request()
missing_messages = []
for i in range(num_messages):
sending_node, receiving_node, receiving_display_name = nodes[i % 2]
result = self.send_and_wait_for_message(
sending_node, receiving_node, receiving_display_name, i, timeout_secs)
timestamp, message_text, message_id, response = result
if not response:
missing_messages.append((timestamp, message_text, message_id, sending_node.name))
else:
messages.append((timestamp, message_text, message_id, sending_node.name))
self.first_node.stop()
self.second_node.stop()
if missing_messages:
formatted_missing_messages = [
f"Timestamp: {ts}, Message: {msg}, ID: {mid}, Sender: {snd}"
for ts, msg, mid, snd in missing_messages
]
raise AssertionError(
f"{len(missing_messages)} messages out of {num_messages} were not received: "
+ "\n".join(formatted_missing_messages)
)
def send_and_wait_for_message(self, sending_node, receiving_node, display_name, index, timeout=10):
receiving_node_pubkey = receiving_node.get_pubkey(display_name)
message_text = f"message_from_{sending_node.name}_{index}"
timestamp, message_id, response = self.send_with_timestamp(
sending_node.send_message, receiving_node_pubkey, message_text
)
validator = MessageValidator(response)
validator.run_all_validations(
expected_chat_id=receiving_node_pubkey,
expected_display_name=display_name,
expected_text=message_text
)
try:
messages_new_events = receiving_node.wait_for_complete_signal("messages.new", timeout)
receiving_node.wait_for_signal("message.delivered", timeout)
messages_new_event = None
for event in messages_new_events:
if "chats" in event.get("event", {}):
messages_new_event = event
try:
validator.validate_event_against_response(
messages_new_event,
fields_to_validate={
"text": "text",
"displayName": "displayName",
"id": "id"
}
)
break
except AssertionError as validation_error:
logger.error(f"Validation failed for event: {messages_new_event}, Error: {validation_error}")
continue
if messages_new_event is None:
raise ValueError("No 'messages.new' event with 'chats' data found within the timeout period.")
except (TimeoutError, ValueError) as e:
logger.error(f"Signal validation failed: {str(e)}")
return timestamp, message_text, message_id, None
return timestamp, message_text, message_id, response
def test_one_to_one_message_with_latency(self):
with self.add_latency():
self.test_one_to_one_message_baseline()
def test_one_to_one_message_with_packet_loss(self):
with self.add_packet_loss():
self.test_one_to_one_message_baseline()
def test_one_to_one_message_with_low_bandwidth(self):
with self.add_low_bandwidth():
self.test_one_to_one_message_baseline()
def test_one_to_one_message_with_node_pause_30_seconds(self):
self.accept_contact_request()
with self.node_pause(self.first_node):
message = str(uuid4())
self.second_node.send_message(self.first_node_pubkey, message)
delay(30)
assert self.second_node.wait_for_signal("messages.new")

View File

@ -2,7 +2,6 @@ from src.libs.custom_logger import get_custom_logger
logger = get_custom_logger(__name__)
class ContactRequestValidator:
def __init__(self, response):
self.response = response
@ -16,12 +15,27 @@ class ContactRequestValidator:
assert len(chats) > 0, "No chats found in the response"
chat = chats[0]
assert chat.get("id") == expected_chat_id, f"Chat ID mismatch: Expected {expected_chat_id}"
assert chat.get("name").startswith("0x"), "Invalid chat name format"
actual_chat_id = chat.get("id")
assert actual_chat_id == expected_chat_id, (
f"Chat ID mismatch: Expected '{expected_chat_id}', found '{actual_chat_id}'"
)
actual_chat_name = chat.get("name")
assert actual_chat_name.startswith("0x"), (
f"Invalid chat name format: Expected name to start with '0x', found '{actual_chat_name}'"
)
last_message = chat.get("lastMessage", {})
assert last_message.get("text") == expected_text, "Message text mismatch"
assert last_message.get("contactRequestState") == 1, "Unexpected contact request state"
actual_text = last_message.get("text")
assert actual_text == expected_text, (
f"Message text mismatch: Expected '{expected_text}', found '{actual_text}'"
)
actual_contact_request_state = last_message.get("contactRequestState")
assert actual_contact_request_state == 1, (
f"Unexpected contact request state: Expected '1', found '{actual_contact_request_state}'"
)
assert "compressedKey" in last_message, "Missing 'compressedKey' in last message"
def validate_event_against_response(self, event, fields_to_validate):
@ -35,7 +49,7 @@ class ContactRequestValidator:
response_value = response_chat.get("lastMessage", {}).get(response_field)
event_value = event_chat.get("lastMessage", {}).get(event_field)
assert response_value == event_value, (
f"Mismatch for '{response_field}': expected '{response_value}', got '{event_value}'"
f"Mismatch for '{response_field}': Expected '{response_value}', found '{event_value}'"
)
def run_all_validations(self, expected_chat_id, expected_display_name, expected_text):

View File

@ -0,0 +1,54 @@
from src.libs.custom_logger import get_custom_logger
logger = get_custom_logger(__name__)
class MessageValidator:
def __init__(self, response):
self.response = response
def validate_response_structure(self):
assert self.response.get("jsonrpc") == "2.0", "Invalid JSON-RPC version"
assert "result" in self.response, "Missing 'result' in response"
def validate_chat_data(self, expected_chat_id, expected_display_name, expected_text):
chats = self.response["result"].get("chats", [])
assert len(chats) > 0, "No chats found in the response"
chat = chats[0]
actual_chat_id = chat.get("id")
assert actual_chat_id == expected_chat_id, (
f"Chat ID mismatch: Expected '{expected_chat_id}', found '{actual_chat_id}'"
)
actual_chat_name = chat.get("name")
assert actual_chat_name.startswith("0x"), (
f"Invalid chat name format: Expected name to start with '0x', found '{actual_chat_name}'"
)
last_message = chat.get("lastMessage", {})
actual_text = last_message.get("text")
assert actual_text == expected_text, (
f"Message text mismatch: Expected '{expected_text}', found '{actual_text}'"
)
assert "compressedKey" in last_message, "Missing 'compressedKey' in last message"
def validate_event_against_response(self, event, fields_to_validate):
chats_in_event = event.get("event", {}).get("chats", [])
assert len(chats_in_event) > 0, "No chats found in the event"
response_chat = self.response["result"]["chats"][0]
event_chat = chats_in_event[0]
for response_field, event_field in fields_to_validate.items():
response_value = response_chat.get("lastMessage", {}).get(response_field)
event_value = event_chat.get("lastMessage", {}).get(event_field)
assert response_value == event_value, (
f"Mismatch for '{response_field}': Expected '{response_value}', found '{event_value}'"
)
def run_all_validations(self, expected_chat_id, expected_display_name, expected_text):
self.validate_response_structure()
self.validate_chat_data(expected_chat_id, expected_display_name, expected_text)
logger.info("All validations passed for the one-to-one message response.")