mirror of
https://github.com/trustgraph-ai/trustgraph.git
synced 2026-04-25 00:16:23 +02:00
Fix tests broken by the recent RabbitMQ/Cassandra async fixes (#815)
- Fix invalid key in config causing rogue warning - Fix asyncio test tags
This commit is contained in:
parent
fdb52a6bfc
commit
22096e07e2
9 changed files with 76 additions and 43 deletions
|
|
@ -9,6 +9,7 @@ tool usage patterns.
|
|||
import pytest
|
||||
from unittest.mock import Mock, AsyncMock
|
||||
import asyncio
|
||||
import inspect
|
||||
from collections import defaultdict
|
||||
|
||||
|
||||
|
|
@ -133,7 +134,7 @@ class TestToolCoordinationLogic:
|
|||
resolved_params[key] = value
|
||||
|
||||
# Execute tool
|
||||
if asyncio.iscoroutinefunction(tool_function):
|
||||
if inspect.iscoroutinefunction(tool_function):
|
||||
result = await tool_function(**resolved_params)
|
||||
else:
|
||||
result = tool_function(**resolved_params)
|
||||
|
|
@ -227,7 +228,7 @@ class TestToolCoordinationLogic:
|
|||
# Simulate async execution with delay
|
||||
await asyncio.sleep(0.001) # Small delay to simulate work
|
||||
|
||||
if asyncio.iscoroutinefunction(tool_function):
|
||||
if inspect.iscoroutinefunction(tool_function):
|
||||
result = await tool_function(**parameters)
|
||||
else:
|
||||
result = tool_function(**parameters)
|
||||
|
|
@ -337,7 +338,7 @@ class TestToolCoordinationLogic:
|
|||
if attempt > 0:
|
||||
await asyncio.sleep(0.001 * (self.backoff_factor ** attempt))
|
||||
|
||||
if asyncio.iscoroutinefunction(tool_function):
|
||||
if inspect.iscoroutinefunction(tool_function):
|
||||
result = await tool_function(**parameters)
|
||||
else:
|
||||
result = tool_function(**parameters)
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ def test_setup_logging_without_loki_configures_console(monkeypatch):
|
|||
kwargs = basic_config.call_args.kwargs
|
||||
assert kwargs["level"] == logging.DEBUG
|
||||
assert kwargs["force"] is True
|
||||
assert "processor-1" in kwargs["format"]
|
||||
assert "%(processor_id)s" in kwargs["format"]
|
||||
assert len(kwargs["handlers"]) == 1
|
||||
logger.info.assert_called_once_with("Logging configured with level: debug")
|
||||
|
||||
|
|
@ -60,11 +60,14 @@ def test_setup_logging_with_loki_enables_queue_listener(monkeypatch):
|
|||
queue_listener = MagicMock()
|
||||
loki_handler = MagicMock()
|
||||
|
||||
noisy_logger = MagicMock()
|
||||
logger_map = {
|
||||
None: root_logger,
|
||||
"trustgraph.base.logging": module_logger,
|
||||
"urllib3": urllib3_logger,
|
||||
"urllib3.connectionpool": connectionpool_logger,
|
||||
"pika": noisy_logger,
|
||||
"cassandra": noisy_logger,
|
||||
}
|
||||
|
||||
monkeypatch.setattr(logging, "basicConfig", basic_config)
|
||||
|
|
|
|||
|
|
@ -330,7 +330,8 @@ class TestUnifiedTableQueries:
|
|||
"""Test queries against the unified rows table"""
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_query_with_index_match(self):
|
||||
@patch('trustgraph.query.rows.cassandra.service.async_execute', new_callable=AsyncMock)
|
||||
async def test_query_with_index_match(self, mock_async_execute):
|
||||
"""Test query execution with matching index"""
|
||||
processor = MagicMock()
|
||||
processor.session = MagicMock()
|
||||
|
|
@ -340,10 +341,10 @@ class TestUnifiedTableQueries:
|
|||
processor.find_matching_index = Processor.find_matching_index.__get__(processor, Processor)
|
||||
processor.query_cassandra = Processor.query_cassandra.__get__(processor, Processor)
|
||||
|
||||
# Mock session execute to return test data
|
||||
# Mock async_execute to return test data
|
||||
mock_row = MagicMock()
|
||||
mock_row.data = {"id": "123", "name": "Test Product", "category": "electronics"}
|
||||
processor.session.execute.return_value = [mock_row]
|
||||
mock_async_execute.return_value = [mock_row]
|
||||
|
||||
schema = RowSchema(
|
||||
name="products",
|
||||
|
|
@ -366,12 +367,12 @@ class TestUnifiedTableQueries:
|
|||
|
||||
# Verify Cassandra was connected and queried
|
||||
processor.connect_cassandra.assert_called_once()
|
||||
processor.session.execute.assert_called_once()
|
||||
mock_async_execute.assert_called_once()
|
||||
|
||||
# Verify query structure - should query unified rows table
|
||||
call_args = processor.session.execute.call_args
|
||||
query = call_args[0][0]
|
||||
params = call_args[0][1]
|
||||
call_args = mock_async_execute.call_args
|
||||
query = call_args[0][1]
|
||||
params = call_args[0][2]
|
||||
|
||||
assert "SELECT data, source FROM test_user.rows" in query
|
||||
assert "collection = %s" in query
|
||||
|
|
@ -390,7 +391,8 @@ class TestUnifiedTableQueries:
|
|||
assert results[0]["category"] == "electronics"
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_query_without_index_match(self):
|
||||
@patch('trustgraph.query.rows.cassandra.service.async_execute', new_callable=AsyncMock)
|
||||
async def test_query_without_index_match(self, mock_async_execute):
|
||||
"""Test query execution without matching index (scan mode)"""
|
||||
processor = MagicMock()
|
||||
processor.session = MagicMock()
|
||||
|
|
@ -401,12 +403,12 @@ class TestUnifiedTableQueries:
|
|||
processor._matches_filters = Processor._matches_filters.__get__(processor, Processor)
|
||||
processor.query_cassandra = Processor.query_cassandra.__get__(processor, Processor)
|
||||
|
||||
# Mock session execute to return test data
|
||||
# Mock async_execute to return test data
|
||||
mock_row1 = MagicMock()
|
||||
mock_row1.data = {"id": "1", "name": "Product A", "price": "100"}
|
||||
mock_row2 = MagicMock()
|
||||
mock_row2.data = {"id": "2", "name": "Product B", "price": "200"}
|
||||
processor.session.execute.return_value = [mock_row1, mock_row2]
|
||||
mock_async_execute.return_value = [mock_row1, mock_row2]
|
||||
|
||||
schema = RowSchema(
|
||||
name="products",
|
||||
|
|
@ -428,8 +430,8 @@ class TestUnifiedTableQueries:
|
|||
)
|
||||
|
||||
# Query should use ALLOW FILTERING for scan
|
||||
call_args = processor.session.execute.call_args
|
||||
query = call_args[0][0]
|
||||
call_args = mock_async_execute.call_args
|
||||
query = call_args[0][1]
|
||||
|
||||
assert "ALLOW FILTERING" in query
|
||||
|
||||
|
|
|
|||
|
|
@ -72,7 +72,6 @@ def processor(mock_pulsar_client, sample_schemas):
|
|||
return proc
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
class TestNLPQueryProcessor:
|
||||
"""Test NLP Query service processor"""
|
||||
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@ def processor(mock_pulsar_client):
|
|||
return proc
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
class TestStructuredQueryProcessor:
|
||||
"""Test Structured Query service processor"""
|
||||
|
||||
|
|
|
|||
|
|
@ -160,7 +160,8 @@ class TestRowsCassandraStorageLogic:
|
|||
assert id_field.primary is True
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_object_processing_stores_data_map(self):
|
||||
@patch('trustgraph.storage.rows.cassandra.write.async_execute', new_callable=AsyncMock)
|
||||
async def test_object_processing_stores_data_map(self, mock_async_execute):
|
||||
"""Test that row processing stores data as map<text, text>"""
|
||||
processor = MagicMock()
|
||||
processor.schemas = {
|
||||
|
|
@ -184,6 +185,8 @@ class TestRowsCassandraStorageLogic:
|
|||
processor.collection_exists = MagicMock(return_value=True)
|
||||
processor.on_object = Processor.on_object.__get__(processor, Processor)
|
||||
|
||||
mock_async_execute.return_value = []
|
||||
|
||||
# Create test object
|
||||
test_obj = ExtractedObject(
|
||||
metadata=Metadata(
|
||||
|
|
@ -205,10 +208,10 @@ class TestRowsCassandraStorageLogic:
|
|||
await processor.on_object(msg, None, None)
|
||||
|
||||
# Verify insert was executed
|
||||
processor.session.execute.assert_called()
|
||||
insert_call = processor.session.execute.call_args
|
||||
insert_cql = insert_call[0][0]
|
||||
values = insert_call[0][1]
|
||||
mock_async_execute.assert_called()
|
||||
insert_call = mock_async_execute.call_args
|
||||
insert_cql = insert_call[0][1]
|
||||
values = insert_call[0][2]
|
||||
|
||||
# Verify using unified rows table
|
||||
assert "INSERT INTO test_user.rows" in insert_cql
|
||||
|
|
@ -222,7 +225,8 @@ class TestRowsCassandraStorageLogic:
|
|||
assert values[5] == "" # source
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_object_processing_multiple_indexes(self):
|
||||
@patch('trustgraph.storage.rows.cassandra.write.async_execute', new_callable=AsyncMock)
|
||||
async def test_object_processing_multiple_indexes(self, mock_async_execute):
|
||||
"""Test that row is written once per indexed field"""
|
||||
processor = MagicMock()
|
||||
processor.schemas = {
|
||||
|
|
@ -246,6 +250,8 @@ class TestRowsCassandraStorageLogic:
|
|||
processor.collection_exists = MagicMock(return_value=True)
|
||||
processor.on_object = Processor.on_object.__get__(processor, Processor)
|
||||
|
||||
mock_async_execute.return_value = []
|
||||
|
||||
test_obj = ExtractedObject(
|
||||
metadata=Metadata(
|
||||
id="test-001",
|
||||
|
|
@ -264,12 +270,12 @@ class TestRowsCassandraStorageLogic:
|
|||
await processor.on_object(msg, None, None)
|
||||
|
||||
# Should have 3 inserts (one per indexed field: id, category, status)
|
||||
assert processor.session.execute.call_count == 3
|
||||
assert mock_async_execute.call_count == 3
|
||||
|
||||
# Check that different index_names were used
|
||||
index_names_used = set()
|
||||
for call in processor.session.execute.call_args_list:
|
||||
values = call[0][1]
|
||||
for call in mock_async_execute.call_args_list:
|
||||
values = call[0][2]
|
||||
index_names_used.add(values[2]) # index_name is 3rd value
|
||||
|
||||
assert index_names_used == {"id", "category", "status"}
|
||||
|
|
@ -279,7 +285,8 @@ class TestRowsCassandraStorageBatchLogic:
|
|||
"""Test batch processing logic for unified table implementation"""
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_batch_object_processing(self):
|
||||
@patch('trustgraph.storage.rows.cassandra.write.async_execute', new_callable=AsyncMock)
|
||||
async def test_batch_object_processing(self, mock_async_execute):
|
||||
"""Test processing of batch ExtractedObjects"""
|
||||
processor = MagicMock()
|
||||
processor.schemas = {
|
||||
|
|
@ -302,6 +309,8 @@ class TestRowsCassandraStorageBatchLogic:
|
|||
processor.collection_exists = MagicMock(return_value=True)
|
||||
processor.on_object = Processor.on_object.__get__(processor, Processor)
|
||||
|
||||
mock_async_execute.return_value = []
|
||||
|
||||
# Create batch object with multiple values
|
||||
batch_obj = ExtractedObject(
|
||||
metadata=Metadata(
|
||||
|
|
@ -325,12 +334,12 @@ class TestRowsCassandraStorageBatchLogic:
|
|||
await processor.on_object(msg, None, None)
|
||||
|
||||
# Should have 3 inserts (one per row, one index per row since only primary key)
|
||||
assert processor.session.execute.call_count == 3
|
||||
assert mock_async_execute.call_count == 3
|
||||
|
||||
# Check each insert has different id
|
||||
ids_inserted = set()
|
||||
for call in processor.session.execute.call_args_list:
|
||||
values = call[0][1]
|
||||
for call in mock_async_execute.call_args_list:
|
||||
values = call[0][2]
|
||||
ids_inserted.add(tuple(values[3])) # index_value is 4th value
|
||||
|
||||
assert ids_inserted == {("001",), ("002",), ("003",)}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ with hand-built fake rows.
|
|||
"""
|
||||
|
||||
import pytest
|
||||
from unittest.mock import Mock
|
||||
from unittest.mock import Mock, AsyncMock, patch
|
||||
|
||||
from trustgraph.tables.knowledge import KnowledgeTableStore
|
||||
from trustgraph.schema import (
|
||||
|
|
@ -35,7 +35,10 @@ def _make_store():
|
|||
class TestGetGraphEmbeddings:
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_row_converts_to_entity_embeddings_with_singular_vector(self):
|
||||
@patch('trustgraph.tables.knowledge.async_execute', new_callable=AsyncMock)
|
||||
async def test_row_converts_to_entity_embeddings_with_singular_vector(
|
||||
self, mock_async_execute
|
||||
):
|
||||
"""
|
||||
Cassandra rows return entities as a list of [entity_tuple, vector]
|
||||
pairs in row[3]. The deserializer must construct EntityEmbeddings
|
||||
|
|
@ -56,8 +59,8 @@ class TestGetGraphEmbeddings:
|
|||
|
||||
store = _make_store()
|
||||
store.cassandra = Mock()
|
||||
store.cassandra.execute = Mock(return_value=[fake_row])
|
||||
store.get_graph_embeddings_stmt = Mock()
|
||||
mock_async_execute.return_value = [fake_row]
|
||||
|
||||
received = []
|
||||
|
||||
|
|
@ -72,7 +75,8 @@ class TestGetGraphEmbeddings:
|
|||
)
|
||||
|
||||
# Assert
|
||||
store.cassandra.execute.assert_called_once_with(
|
||||
mock_async_execute.assert_called_once_with(
|
||||
store.cassandra,
|
||||
store.get_graph_embeddings_stmt,
|
||||
("alice", "doc-1"),
|
||||
)
|
||||
|
|
@ -102,15 +106,16 @@ class TestGetGraphEmbeddings:
|
|||
assert ge.entities[2].entity.value == "a literal entity"
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_empty_entities_blob_yields_empty_list(self):
|
||||
@patch('trustgraph.tables.knowledge.async_execute', new_callable=AsyncMock)
|
||||
async def test_empty_entities_blob_yields_empty_list(self, mock_async_execute):
|
||||
"""row[3] being None / empty must produce a GraphEmbeddings with
|
||||
no entities, not raise."""
|
||||
fake_row = (None, None, None, None)
|
||||
|
||||
store = _make_store()
|
||||
store.cassandra = Mock()
|
||||
store.cassandra.execute = Mock(return_value=[fake_row])
|
||||
store.get_graph_embeddings_stmt = Mock()
|
||||
mock_async_execute.return_value = [fake_row]
|
||||
|
||||
received = []
|
||||
|
||||
|
|
@ -123,7 +128,8 @@ class TestGetGraphEmbeddings:
|
|||
assert received[0].entities == []
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_multiple_rows_each_emit_one_message(self):
|
||||
@patch('trustgraph.tables.knowledge.async_execute', new_callable=AsyncMock)
|
||||
async def test_multiple_rows_each_emit_one_message(self, mock_async_execute):
|
||||
fake_rows = [
|
||||
(None, None, None, [
|
||||
(("http://example.org/a", True), [1.0]),
|
||||
|
|
@ -135,8 +141,8 @@ class TestGetGraphEmbeddings:
|
|||
|
||||
store = _make_store()
|
||||
store.cassandra = Mock()
|
||||
store.cassandra.execute = Mock(return_value=fake_rows)
|
||||
store.get_graph_embeddings_stmt = Mock()
|
||||
mock_async_execute.return_value = fake_rows
|
||||
|
||||
received = []
|
||||
|
||||
|
|
@ -157,7 +163,8 @@ class TestGetTriples:
|
|||
the same Metadata construction. Cover it for parity."""
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_row_converts_to_triples(self):
|
||||
@patch('trustgraph.tables.knowledge.async_execute', new_callable=AsyncMock)
|
||||
async def test_row_converts_to_triples(self, mock_async_execute):
|
||||
# row[3] is a list of (s_val, s_uri, p_val, p_uri, o_val, o_uri)
|
||||
fake_row = (
|
||||
None, None, None,
|
||||
|
|
@ -172,8 +179,8 @@ class TestGetTriples:
|
|||
|
||||
store = _make_store()
|
||||
store.cassandra = Mock()
|
||||
store.cassandra.execute = Mock(return_value=[fake_row])
|
||||
store.get_triples_stmt = Mock()
|
||||
mock_async_execute.return_value = [fake_row]
|
||||
|
||||
received = []
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue