added store_test_cursor negative cases and edge cases

This commit is contained in:
shashankshampi 2024-09-16 12:45:56 +05:30
parent cc8bae75c1
commit 6d942d8876
3 changed files with 180 additions and 29 deletions

1
.gitignore vendored
View File

@ -1,5 +1,6 @@
# Custom
log/
.idea/
.vscode
allure-results/
postgresql

View File

@ -1,4 +1,7 @@
import inspect
import requests
from src.libs.custom_logger import get_custom_logger
import pytest
import allure
@ -186,9 +189,9 @@ class StepsStore(StepsCommon):
return store_response
@allure.step
def check_published_message_is_stored(
def get_store_messages_with_errors(
self,
store_node=None,
node=None,
peer_addr=None,
include_data=None,
pubsub_topic=None,
@ -198,25 +201,17 @@ class StepsStore(StepsCommon):
hashes=None,
cursor=None,
page_size=None,
ascending=None,
ascending="true",
store_v="v3",
message_to_check=None,
**kwargs,
):
if pubsub_topic is None:
pubsub_topic = self.test_pubsub_topic
if message_to_check is None:
message_to_check = self.message
if store_node is None:
store_node = self.store_nodes
elif not isinstance(store_node, list):
store_node = [store_node]
else:
store_node = store_node
for node in store_node:
logger.debug(f"Checking that peer {node.image} can find the stored message")
self.store_response = self.get_messages_from_store(
node=node,
"""
This method calls the original get_store_messages and returns the actual
error response from the service, if present.
"""
try:
# Call the original get_store_messages method
store_response = node.get_store_messages(
peer_addr=peer_addr,
include_data=include_data,
pubsub_topic=pubsub_topic,
@ -231,17 +226,79 @@ class StepsStore(StepsCommon):
**kwargs,
)
assert self.store_response.messages, f"Peer {node.image} couldn't find any messages. Actual response: {self.store_response.resp_json}"
assert len(self.store_response.messages) >= 1, "Expected at least 1 message but got none"
store_message_index = -1 # we are looking for the last and most recent message in the store
waku_message = WakuMessage([self.store_response.messages[store_message_index:]])
if store_v == "v1":
waku_message.assert_received_message(message_to_check)
else:
expected_hash = self.compute_message_hash(pubsub_topic, message_to_check)
assert expected_hash == self.store_response.message_hash(
store_message_index
), f"Message hash returned by store doesn't match the computed message hash {expected_hash}"
# Check if the response status code indicates an error (400 or higher)
if store_response.status_code >= 400:
# If the response is plain text, just return it as the error message
return {"status_code": store_response.status_code, "error_message": store_response.text} # Use plain text response directly
# Otherwise, return the successful response
response_json = store_response.json()
response_json["status_code"] = store_response.status_code
return response_json
except requests.exceptions.HTTPError as http_err:
# Handle HTTP errors separately
return {"status_code": http_err.response.status_code, "error_message": http_err.response.text}
except Exception as e:
# Handle unexpected errors and return as 500
return {"status_code": 500, "error_message": str(e)}
@allure.step
def get_store_messages_with_errors(
self,
node=None,
peer_addr=None,
include_data=None,
pubsub_topic=None,
content_topics=None,
start_time=None,
end_time=None,
hashes=None,
cursor=None,
page_size=None,
ascending="true",
store_v="v3",
**kwargs,
):
"""
This method calls the original get_store_messages and returns the actual
error response from the service, if present.
"""
try:
# Call the original get_store_messages method
store_response = node.get_store_messages(
peer_addr=peer_addr,
include_data=include_data,
pubsub_topic=pubsub_topic,
content_topics=content_topics,
start_time=start_time,
end_time=end_time,
hashes=hashes,
cursor=cursor,
page_size=page_size,
ascending=ascending,
store_v=store_v,
**kwargs,
)
print("my store_response: ", store_response)
# Check if the response has a status code >= 400, indicating an error
if store_response.status_code >= 400:
# Return the status code and the plain text error message directly
return {"status_code": store_response.status_code, "error_message": store_response.text} # Handling plain text response
# Otherwise, return the successful response as JSON
response_json = store_response.json()
response_json["status_code"] = store_response.status_code
return response_json
except requests.exceptions.HTTPError as http_err:
# Handle HTTP errors separately
return {"status_code": http_err.response.status_code, "error_message": http_err.response.text}
except Exception as e:
# Handle unexpected errors and return as 500
return {"status_code": 500, "error_message": str(e)}
@allure.step
def check_store_returns_empty_response(self, pubsub_topic=None):

View File

@ -102,3 +102,96 @@ class TestCursor(StepsStore):
for node in self.store_nodes:
store_response = self.get_messages_from_store(node, page_size=100, cursor=cursor)
assert not store_response.messages, "Messages found"
# Addon on test
# Ensure that when the cursor is an empty string (""), the API returns the first page of data.
def test_empty_cursor(self):
for i in range(10):
self.publish_message(message=self.create_message(payload=to_base64(f"Message_{i}")))
for node in self.store_nodes:
store_response = self.get_messages_from_store(node, page_size=5, cursor="")
assert store_response.status_code == 200, f"Expected status code 200, got {store_response.status_code}"
assert len(store_response.messages) == 5, "Message count mismatch with empty cursor"
# Test the scenario where the cursor points near the last few messages, ensuring proper pagination.
def test_cursor_near_end(self):
message_hash_list = []
for i in range(10):
message = self.create_message(payload=to_base64(f"Message_{i}"))
self.publish_message(message=message)
message_hash_list.append(self.compute_message_hash(self.test_pubsub_topic, message))
for node in self.store_nodes:
store_response = self.get_messages_from_store(node, page_size=5)
cursor = store_response.pagination_cursor
store_response = self.get_messages_from_store(node, page_size=5, cursor=cursor)
assert len(store_response.messages) == 5, "Message count mismatch near the end"
# Test how the API handles a cursor that points to a message that no longer exists.
def test_cursor_pointing_to_deleted_message(self):
# Publish some messages
for i in range(10):
self.publish_message(message=self.create_message(payload=to_base64(f"Message_{i}")))
# Create a deleted message and compute its hash as the cursor
deleted_message = self.create_message(payload=to_base64("Deleted_Message"))
cursor = self.compute_message_hash(self.test_pubsub_topic, deleted_message)
# Test the store response
for node in self.store_nodes:
store_response = self.get_store_messages_with_errors(node=node, page_size=100, cursor=cursor)
# Assert that the error code is 500 for the deleted message scenario
assert store_response["status_code"] == 500, f"Expected status code 500, got {store_response['status_code']}"
# Define a partial expected error message (since the actual response includes more details)
expected_error_fragment = "error in handleSelfStoreRequest: BAD_RESPONSE: archive error: DIRVER_ERROR: cursor not found"
# Extract the actual error message and ensure it contains the expected error fragment
actual_error_message = store_response["error_message"]
assert (
expected_error_fragment in actual_error_message
), f"Expected error message fragment '{expected_error_fragment}', but got '{actual_error_message}'"
# Test if the API returns the expected messages when the cursor points to the first message in the store.
def test_cursor_equal_to_first_message(self):
message_hash_list = []
for i in range(10):
message = self.create_message(payload=to_base64(f"Message_{i}"))
self.publish_message(message=message)
message_hash_list.append(self.compute_message_hash(self.test_pubsub_topic, message))
cursor = message_hash_list[0] # Cursor points to the first message
for node in self.store_nodes:
store_response = self.get_messages_from_store(node, page_size=100, cursor=cursor)
assert len(store_response.messages) == 9, "Message count mismatch from the first cursor"
# Test behavior when the cursor points exactly at the page size boundary.
def test_cursor_at_page_size_boundary(self):
message_hash_list = []
for i in range(10):
message = self.create_message(payload=to_base64(f"Message_{i}"))
self.publish_message(message=message)
message_hash_list.append(self.compute_message_hash(self.test_pubsub_topic, message))
# Set page size to 5, checking paginationCursor after both fetches
for node in self.store_nodes:
# Fetch the first page of messages
store_response = self.get_messages_from_store(node, page_size=5)
# Check if we received exactly 5 messages
assert len(store_response.messages) == 5, "Message count mismatch on first page"
# Validate that paginationCursor exists because we are not at the boundary
assert store_response.pagination_cursor is not None, "paginationCursor should be present when not at the boundary"
cursor = store_response.pagination_cursor
# Fetch the next page using the cursor
store_response = self.get_messages_from_store(node, page_size=5, cursor=cursor)
# Check if we received exactly 5 more messages
assert len(store_response.messages) == 5, "Message count mismatch at page size boundary"
# Validate that paginationCursor is **not** present when we reach the boundary (end of pagination)
assert store_response.pagination_cursor is None, "paginationCursor should be absent when at the boundary"