import json
import demistomock as demisto
import pytest
from CommonServerPython import get_demisto_version
from SearchIndicatorRelationships import handle_stix_types, search_relationships, to_context
def util_load_json(path):
with open(path, encoding="utf-8") as f:
return json.loads(f.read())
def test_to_context_verbose_false():
"""
Given:
- the data section of the contents of the servers response to the SearchRelationships command.
When:
- running to_context function with verbose false.
Then:
- Ensure that the context is as expected.
"""
mock_response = util_load_json("test_data/searchRelationships-response.json")
response = to_context(mock_response, False)
expected = util_load_json("test_data/verbose_false_expected.json")
assert expected == response
def test_to_context_verbose_true():
"""
Given:
- the data section of the contents of the servers response to the SearchRelationships command.
When:
- running to_context function with verbose true.
Then:
- Ensure that the context is as expected.
"""
mock_response = util_load_json("test_data/searchRelationships-response.json")
response = to_context(mock_response, True)
expected = util_load_json("test_data/verbose_true_expected.json")
assert expected == response
def test_handle_stix_types(mocker):
mocker.patch.object(demisto, "demistoVersion", return_value={"version": "6.1.0"})
entity_types = "STIX Malware,STIX Attack Pattern,STIX Threat Actor,STIX Tool"
entity_types = handle_stix_types(entity_types)
assert entity_types == "STIX Malware,STIX Attack Pattern,STIX Threat Actor,STIX Tool"
@pytest.mark.parametrize(
"demisto_version, expected_result", [("6.5.0", ["mock_result_1"]), ("6.6.0", ["mock_result_2"]), ("7.0.0", ["mock_result_3"])]
)
def test_search_relationship_command_args_by_demisto_version(mocker, demisto_version, expected_result):
"""
Given:
XSOAR versions:
1. 6.5.0
2. 6.6.0
3. 7.0.0
When:
Calling search_relationships method.
Then:
Make sure that for each version, the correct implementation of searchRelationships server script is called:
- For version 6.5.0:
- The command is called using `executeCommand`.
- The payload is sent in the expected `searchRelationships` format.
- An XSOAR entry is returned.
- For versions 6.6.0 and 7.0.0:
- the command is called using `demisto.searchRelationships`,
- The payload is sent in a RelationshipFilter structure.
- The data is returned in a RelationshipSearchResponse format.
"""
get_demisto_version._version = None # clear cache between runs of the test
def searchRelationships(args):
assert demisto_version >= "6.6.0"
assert isinstance(args.get("entities"), list)
return {"data": expected_result}
def executeCommand(command_name, args):
assert command_name == "searchRelationships"
assert demisto_version < "6.6.0"
assert isinstance(args.get("entities"), str)
return [{"Contents": {"data": expected_result}, "Type": "not_error"}]
mocker.patch.object(demisto, "demistoVersion", return_value={"version": demisto_version})
mocker.patch.object(demisto, "executeCommand", side_effect=executeCommand)
mocker.patch.object(demisto, "searchRelationships", side_effect=searchRelationships)
result = search_relationships(entities="1.1.1.1,8.8.8.8")
result = result.get("data", []) # handle both old and new response formats
assert result == expected_result
@pytest.mark.parametrize("search_after, expected_type", [(["timestamp1", "id1"], dict), (None, dict), ([], dict)])
def test_search_relationships_with_search_after(mocker, search_after, expected_type):
"""
Given:
Different searchAfter parameter values:
1. searchAfter as list ["timestamp1", "id1"]
2. searchAfter as None
3. searchAfter as empty list []
When:
Calling search_relationships method with searchAfter parameter.
Then:
Make sure that search_relationships returns a dict for all searchAfter parameter variations.
"""
mocker.patch.object(demisto, "demistoVersion", return_value={"version": "6.6.0"})
mocker.patch.object(demisto, "searchRelationships", return_value={"data": []})
result = search_relationships(searchAfter=search_after)
assert isinstance(result, expected_type), "search_relationships should return a dict"
@pytest.mark.parametrize(
"search_after, expected_pagination", [(["test_timestamp", "test_id"], [["test_timestamp", "test_id"]]), (None, [])]
)
def test_to_context_with_search_after(search_after, expected_pagination):
"""
Given:
Mock relationships data with different SearchAfter values:
1. SearchAfter as list ["test_timestamp", "test_id"]
2. SearchAfter as None
When:
Calling to_context method with the mock relationships data.
Then:
Make sure that:
- Context contains RelationshipsPagination key
- RelationshipsPagination contains the expected value based on SearchAfter
- When SearchAfter is None, RelationshipsPagination should be empty
"""
mock_relationships_data = {"SearchAfter": search_after, "data": []}
context = to_context(mock_relationships_data, False)
assert "RelationshipsPagination" in context, "Context should contain RelationshipsPagination"
assert context["RelationshipsPagination"] == expected_pagination