2025-09-02 17:58:53 +01:00
|
|
|
"""
|
|
|
|
|
Contract tests for document embeddings message schemas and translators
|
|
|
|
|
Ensures that message formats remain consistent across services
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
import pytest
|
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
|
|
2026-03-09 10:53:44 +00:00
|
|
|
from trustgraph.schema import DocumentEmbeddingsRequest, DocumentEmbeddingsResponse, ChunkMatch, Error
|
2025-09-02 17:58:53 +01:00
|
|
|
from trustgraph.messaging.translators.embeddings_query import (
|
|
|
|
|
DocumentEmbeddingsRequestTranslator,
|
|
|
|
|
DocumentEmbeddingsResponseTranslator
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TestDocumentEmbeddingsRequestContract:
|
|
|
|
|
"""Test DocumentEmbeddingsRequest schema contract"""
|
|
|
|
|
|
|
|
|
|
def test_request_schema_fields(self):
|
|
|
|
|
"""Test that DocumentEmbeddingsRequest has expected fields"""
|
|
|
|
|
# Create a request
|
|
|
|
|
request = DocumentEmbeddingsRequest(
|
2026-03-09 10:53:44 +00:00
|
|
|
vector=[0.1, 0.2, 0.3],
|
2025-09-02 17:58:53 +01:00
|
|
|
limit=10,
|
|
|
|
|
user="test_user",
|
|
|
|
|
collection="test_collection"
|
|
|
|
|
)
|
2026-03-07 23:38:09 +00:00
|
|
|
|
2025-09-02 17:58:53 +01:00
|
|
|
# Verify all expected fields exist
|
2026-03-09 10:53:44 +00:00
|
|
|
assert hasattr(request, 'vector')
|
2025-09-02 17:58:53 +01:00
|
|
|
assert hasattr(request, 'limit')
|
|
|
|
|
assert hasattr(request, 'user')
|
|
|
|
|
assert hasattr(request, 'collection')
|
2026-03-07 23:38:09 +00:00
|
|
|
|
2025-09-02 17:58:53 +01:00
|
|
|
# Verify field values
|
2026-03-09 10:53:44 +00:00
|
|
|
assert request.vector == [0.1, 0.2, 0.3]
|
2025-09-02 17:58:53 +01:00
|
|
|
assert request.limit == 10
|
|
|
|
|
assert request.user == "test_user"
|
|
|
|
|
assert request.collection == "test_collection"
|
|
|
|
|
|
Pub/sub abstraction: decouple from Pulsar (#751)
Remove Pulsar-specific concepts from application code so that
the pub/sub backend is swappable via configuration.
Rename translators:
- to_pulsar/from_pulsar → decode/encode across all translator
classes, dispatch handlers, and tests (55+ files)
- from_response_with_completion → encode_with_completion
- Remove pulsar.schema.Record from translator base class
Queue naming (CLASS:TOPICSPACE:TOPIC):
- Replace topic() helper with queue() using new format:
flow:tg:name, request:tg:name, response:tg:name, state:tg:name
- Queue class implies persistence/TTL (no QoS in names)
- Update Pulsar backend map_topic() to parse new format
- Librarian queues use flow class (persistent, for chunking)
- Config push uses state class (persistent, last-value)
- Remove 15 dead topic imports from schema files
- Update init_trustgraph.py namespace: config → state
Confine Pulsar to pulsar_backend.py:
- Delete legacy PulsarClient class from pubsub.py
- Move add_args to add_pubsub_args() with standalone flag
for CLI tools (defaults to localhost)
- PulsarBackendConsumer.receive() catches _pulsar.Timeout,
raises standard TimeoutError
- Remove Pulsar imports from: async_processor, flow_processor,
log_level, all 11 client files, 4 storage writers, gateway
service, gateway config receiver
- Remove log_level/LoggerLevel from client API
- Rewrite tg-monitor-prompts to use backend abstraction
- Update tg-dump-queues to use add_pubsub_args
Also: pubsub-abstraction.md tech spec covering problem statement,
design goals, as-is requirements, candidate broker assessment,
approach, and implementation order.
2026-04-01 20:16:53 +01:00
|
|
|
def test_request_translator_decode(self):
|
2025-09-02 17:58:53 +01:00
|
|
|
"""Test request translator converts dict to Pulsar schema"""
|
|
|
|
|
translator = DocumentEmbeddingsRequestTranslator()
|
2026-03-07 23:38:09 +00:00
|
|
|
|
2025-09-02 17:58:53 +01:00
|
|
|
data = {
|
2026-03-09 10:53:44 +00:00
|
|
|
"vector": [0.1, 0.2, 0.3, 0.4],
|
2025-09-02 17:58:53 +01:00
|
|
|
"limit": 5,
|
|
|
|
|
"user": "custom_user",
|
|
|
|
|
"collection": "custom_collection"
|
|
|
|
|
}
|
2026-03-07 23:38:09 +00:00
|
|
|
|
Pub/sub abstraction: decouple from Pulsar (#751)
Remove Pulsar-specific concepts from application code so that
the pub/sub backend is swappable via configuration.
Rename translators:
- to_pulsar/from_pulsar → decode/encode across all translator
classes, dispatch handlers, and tests (55+ files)
- from_response_with_completion → encode_with_completion
- Remove pulsar.schema.Record from translator base class
Queue naming (CLASS:TOPICSPACE:TOPIC):
- Replace topic() helper with queue() using new format:
flow:tg:name, request:tg:name, response:tg:name, state:tg:name
- Queue class implies persistence/TTL (no QoS in names)
- Update Pulsar backend map_topic() to parse new format
- Librarian queues use flow class (persistent, for chunking)
- Config push uses state class (persistent, last-value)
- Remove 15 dead topic imports from schema files
- Update init_trustgraph.py namespace: config → state
Confine Pulsar to pulsar_backend.py:
- Delete legacy PulsarClient class from pubsub.py
- Move add_args to add_pubsub_args() with standalone flag
for CLI tools (defaults to localhost)
- PulsarBackendConsumer.receive() catches _pulsar.Timeout,
raises standard TimeoutError
- Remove Pulsar imports from: async_processor, flow_processor,
log_level, all 11 client files, 4 storage writers, gateway
service, gateway config receiver
- Remove log_level/LoggerLevel from client API
- Rewrite tg-monitor-prompts to use backend abstraction
- Update tg-dump-queues to use add_pubsub_args
Also: pubsub-abstraction.md tech spec covering problem statement,
design goals, as-is requirements, candidate broker assessment,
approach, and implementation order.
2026-04-01 20:16:53 +01:00
|
|
|
result = translator.decode(data)
|
2026-03-07 23:38:09 +00:00
|
|
|
|
2025-09-02 17:58:53 +01:00
|
|
|
assert isinstance(result, DocumentEmbeddingsRequest)
|
2026-03-09 10:53:44 +00:00
|
|
|
assert result.vector == [0.1, 0.2, 0.3, 0.4]
|
2025-09-02 17:58:53 +01:00
|
|
|
assert result.limit == 5
|
|
|
|
|
assert result.user == "custom_user"
|
|
|
|
|
assert result.collection == "custom_collection"
|
|
|
|
|
|
Pub/sub abstraction: decouple from Pulsar (#751)
Remove Pulsar-specific concepts from application code so that
the pub/sub backend is swappable via configuration.
Rename translators:
- to_pulsar/from_pulsar → decode/encode across all translator
classes, dispatch handlers, and tests (55+ files)
- from_response_with_completion → encode_with_completion
- Remove pulsar.schema.Record from translator base class
Queue naming (CLASS:TOPICSPACE:TOPIC):
- Replace topic() helper with queue() using new format:
flow:tg:name, request:tg:name, response:tg:name, state:tg:name
- Queue class implies persistence/TTL (no QoS in names)
- Update Pulsar backend map_topic() to parse new format
- Librarian queues use flow class (persistent, for chunking)
- Config push uses state class (persistent, last-value)
- Remove 15 dead topic imports from schema files
- Update init_trustgraph.py namespace: config → state
Confine Pulsar to pulsar_backend.py:
- Delete legacy PulsarClient class from pubsub.py
- Move add_args to add_pubsub_args() with standalone flag
for CLI tools (defaults to localhost)
- PulsarBackendConsumer.receive() catches _pulsar.Timeout,
raises standard TimeoutError
- Remove Pulsar imports from: async_processor, flow_processor,
log_level, all 11 client files, 4 storage writers, gateway
service, gateway config receiver
- Remove log_level/LoggerLevel from client API
- Rewrite tg-monitor-prompts to use backend abstraction
- Update tg-dump-queues to use add_pubsub_args
Also: pubsub-abstraction.md tech spec covering problem statement,
design goals, as-is requirements, candidate broker assessment,
approach, and implementation order.
2026-04-01 20:16:53 +01:00
|
|
|
def test_request_translator_decode_with_defaults(self):
|
2025-09-02 17:58:53 +01:00
|
|
|
"""Test request translator uses correct defaults"""
|
|
|
|
|
translator = DocumentEmbeddingsRequestTranslator()
|
2026-03-07 23:38:09 +00:00
|
|
|
|
2025-09-02 17:58:53 +01:00
|
|
|
data = {
|
2026-03-09 10:53:44 +00:00
|
|
|
"vector": [0.1, 0.2]
|
2025-09-02 17:58:53 +01:00
|
|
|
# No limit, user, or collection provided
|
|
|
|
|
}
|
2026-03-07 23:38:09 +00:00
|
|
|
|
Pub/sub abstraction: decouple from Pulsar (#751)
Remove Pulsar-specific concepts from application code so that
the pub/sub backend is swappable via configuration.
Rename translators:
- to_pulsar/from_pulsar → decode/encode across all translator
classes, dispatch handlers, and tests (55+ files)
- from_response_with_completion → encode_with_completion
- Remove pulsar.schema.Record from translator base class
Queue naming (CLASS:TOPICSPACE:TOPIC):
- Replace topic() helper with queue() using new format:
flow:tg:name, request:tg:name, response:tg:name, state:tg:name
- Queue class implies persistence/TTL (no QoS in names)
- Update Pulsar backend map_topic() to parse new format
- Librarian queues use flow class (persistent, for chunking)
- Config push uses state class (persistent, last-value)
- Remove 15 dead topic imports from schema files
- Update init_trustgraph.py namespace: config → state
Confine Pulsar to pulsar_backend.py:
- Delete legacy PulsarClient class from pubsub.py
- Move add_args to add_pubsub_args() with standalone flag
for CLI tools (defaults to localhost)
- PulsarBackendConsumer.receive() catches _pulsar.Timeout,
raises standard TimeoutError
- Remove Pulsar imports from: async_processor, flow_processor,
log_level, all 11 client files, 4 storage writers, gateway
service, gateway config receiver
- Remove log_level/LoggerLevel from client API
- Rewrite tg-monitor-prompts to use backend abstraction
- Update tg-dump-queues to use add_pubsub_args
Also: pubsub-abstraction.md tech spec covering problem statement,
design goals, as-is requirements, candidate broker assessment,
approach, and implementation order.
2026-04-01 20:16:53 +01:00
|
|
|
result = translator.decode(data)
|
2026-03-07 23:38:09 +00:00
|
|
|
|
2025-09-02 17:58:53 +01:00
|
|
|
assert isinstance(result, DocumentEmbeddingsRequest)
|
2026-03-09 10:53:44 +00:00
|
|
|
assert result.vector == [0.1, 0.2]
|
2025-09-02 17:58:53 +01:00
|
|
|
assert result.limit == 10 # Default
|
|
|
|
|
assert result.user == "trustgraph" # Default
|
|
|
|
|
assert result.collection == "default" # Default
|
|
|
|
|
|
Pub/sub abstraction: decouple from Pulsar (#751)
Remove Pulsar-specific concepts from application code so that
the pub/sub backend is swappable via configuration.
Rename translators:
- to_pulsar/from_pulsar → decode/encode across all translator
classes, dispatch handlers, and tests (55+ files)
- from_response_with_completion → encode_with_completion
- Remove pulsar.schema.Record from translator base class
Queue naming (CLASS:TOPICSPACE:TOPIC):
- Replace topic() helper with queue() using new format:
flow:tg:name, request:tg:name, response:tg:name, state:tg:name
- Queue class implies persistence/TTL (no QoS in names)
- Update Pulsar backend map_topic() to parse new format
- Librarian queues use flow class (persistent, for chunking)
- Config push uses state class (persistent, last-value)
- Remove 15 dead topic imports from schema files
- Update init_trustgraph.py namespace: config → state
Confine Pulsar to pulsar_backend.py:
- Delete legacy PulsarClient class from pubsub.py
- Move add_args to add_pubsub_args() with standalone flag
for CLI tools (defaults to localhost)
- PulsarBackendConsumer.receive() catches _pulsar.Timeout,
raises standard TimeoutError
- Remove Pulsar imports from: async_processor, flow_processor,
log_level, all 11 client files, 4 storage writers, gateway
service, gateway config receiver
- Remove log_level/LoggerLevel from client API
- Rewrite tg-monitor-prompts to use backend abstraction
- Update tg-dump-queues to use add_pubsub_args
Also: pubsub-abstraction.md tech spec covering problem statement,
design goals, as-is requirements, candidate broker assessment,
approach, and implementation order.
2026-04-01 20:16:53 +01:00
|
|
|
def test_request_translator_encode(self):
|
2025-09-02 17:58:53 +01:00
|
|
|
"""Test request translator converts Pulsar schema to dict"""
|
|
|
|
|
translator = DocumentEmbeddingsRequestTranslator()
|
2026-03-07 23:38:09 +00:00
|
|
|
|
2025-09-02 17:58:53 +01:00
|
|
|
request = DocumentEmbeddingsRequest(
|
2026-03-09 10:53:44 +00:00
|
|
|
vector=[0.5, 0.6],
|
2025-09-02 17:58:53 +01:00
|
|
|
limit=20,
|
|
|
|
|
user="test_user",
|
|
|
|
|
collection="test_collection"
|
|
|
|
|
)
|
2026-03-07 23:38:09 +00:00
|
|
|
|
Pub/sub abstraction: decouple from Pulsar (#751)
Remove Pulsar-specific concepts from application code so that
the pub/sub backend is swappable via configuration.
Rename translators:
- to_pulsar/from_pulsar → decode/encode across all translator
classes, dispatch handlers, and tests (55+ files)
- from_response_with_completion → encode_with_completion
- Remove pulsar.schema.Record from translator base class
Queue naming (CLASS:TOPICSPACE:TOPIC):
- Replace topic() helper with queue() using new format:
flow:tg:name, request:tg:name, response:tg:name, state:tg:name
- Queue class implies persistence/TTL (no QoS in names)
- Update Pulsar backend map_topic() to parse new format
- Librarian queues use flow class (persistent, for chunking)
- Config push uses state class (persistent, last-value)
- Remove 15 dead topic imports from schema files
- Update init_trustgraph.py namespace: config → state
Confine Pulsar to pulsar_backend.py:
- Delete legacy PulsarClient class from pubsub.py
- Move add_args to add_pubsub_args() with standalone flag
for CLI tools (defaults to localhost)
- PulsarBackendConsumer.receive() catches _pulsar.Timeout,
raises standard TimeoutError
- Remove Pulsar imports from: async_processor, flow_processor,
log_level, all 11 client files, 4 storage writers, gateway
service, gateway config receiver
- Remove log_level/LoggerLevel from client API
- Rewrite tg-monitor-prompts to use backend abstraction
- Update tg-dump-queues to use add_pubsub_args
Also: pubsub-abstraction.md tech spec covering problem statement,
design goals, as-is requirements, candidate broker assessment,
approach, and implementation order.
2026-04-01 20:16:53 +01:00
|
|
|
result = translator.encode(request)
|
2026-03-07 23:38:09 +00:00
|
|
|
|
2025-09-02 17:58:53 +01:00
|
|
|
assert isinstance(result, dict)
|
2026-03-09 10:53:44 +00:00
|
|
|
assert result["vector"] == [0.5, 0.6]
|
2025-09-02 17:58:53 +01:00
|
|
|
assert result["limit"] == 20
|
|
|
|
|
assert result["user"] == "test_user"
|
|
|
|
|
assert result["collection"] == "test_collection"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TestDocumentEmbeddingsResponseContract:
|
|
|
|
|
"""Test DocumentEmbeddingsResponse schema contract"""
|
|
|
|
|
|
|
|
|
|
def test_response_schema_fields(self):
|
|
|
|
|
"""Test that DocumentEmbeddingsResponse has expected fields"""
|
2026-03-09 10:53:44 +00:00
|
|
|
# Create a response with chunks
|
2025-09-02 17:58:53 +01:00
|
|
|
response = DocumentEmbeddingsResponse(
|
|
|
|
|
error=None,
|
2026-03-09 10:53:44 +00:00
|
|
|
chunks=[
|
|
|
|
|
ChunkMatch(chunk_id="chunk1", score=0.9),
|
|
|
|
|
ChunkMatch(chunk_id="chunk2", score=0.8),
|
|
|
|
|
ChunkMatch(chunk_id="chunk3", score=0.7)
|
|
|
|
|
]
|
2025-09-02 17:58:53 +01:00
|
|
|
)
|
2026-03-07 23:38:09 +00:00
|
|
|
|
2025-09-02 17:58:53 +01:00
|
|
|
# Verify all expected fields exist
|
|
|
|
|
assert hasattr(response, 'error')
|
2026-03-09 10:53:44 +00:00
|
|
|
assert hasattr(response, 'chunks')
|
2026-03-07 23:38:09 +00:00
|
|
|
|
2025-09-02 17:58:53 +01:00
|
|
|
# Verify field values
|
|
|
|
|
assert response.error is None
|
2026-03-09 10:53:44 +00:00
|
|
|
assert len(response.chunks) == 3
|
|
|
|
|
assert response.chunks[0].chunk_id == "chunk1"
|
|
|
|
|
assert response.chunks[0].score == 0.9
|
2025-09-02 17:58:53 +01:00
|
|
|
|
|
|
|
|
def test_response_schema_with_error(self):
|
|
|
|
|
"""Test response schema with error"""
|
|
|
|
|
error = Error(
|
|
|
|
|
type="query_error",
|
|
|
|
|
message="Database connection failed"
|
|
|
|
|
)
|
2026-03-07 23:38:09 +00:00
|
|
|
|
2025-09-02 17:58:53 +01:00
|
|
|
response = DocumentEmbeddingsResponse(
|
|
|
|
|
error=error,
|
2026-03-09 10:53:44 +00:00
|
|
|
chunks=[]
|
2025-09-02 17:58:53 +01:00
|
|
|
)
|
2026-03-07 23:38:09 +00:00
|
|
|
|
2025-09-02 17:58:53 +01:00
|
|
|
assert response.error == error
|
2026-03-09 10:53:44 +00:00
|
|
|
assert response.chunks == []
|
2025-09-02 17:58:53 +01:00
|
|
|
|
Pub/sub abstraction: decouple from Pulsar (#751)
Remove Pulsar-specific concepts from application code so that
the pub/sub backend is swappable via configuration.
Rename translators:
- to_pulsar/from_pulsar → decode/encode across all translator
classes, dispatch handlers, and tests (55+ files)
- from_response_with_completion → encode_with_completion
- Remove pulsar.schema.Record from translator base class
Queue naming (CLASS:TOPICSPACE:TOPIC):
- Replace topic() helper with queue() using new format:
flow:tg:name, request:tg:name, response:tg:name, state:tg:name
- Queue class implies persistence/TTL (no QoS in names)
- Update Pulsar backend map_topic() to parse new format
- Librarian queues use flow class (persistent, for chunking)
- Config push uses state class (persistent, last-value)
- Remove 15 dead topic imports from schema files
- Update init_trustgraph.py namespace: config → state
Confine Pulsar to pulsar_backend.py:
- Delete legacy PulsarClient class from pubsub.py
- Move add_args to add_pubsub_args() with standalone flag
for CLI tools (defaults to localhost)
- PulsarBackendConsumer.receive() catches _pulsar.Timeout,
raises standard TimeoutError
- Remove Pulsar imports from: async_processor, flow_processor,
log_level, all 11 client files, 4 storage writers, gateway
service, gateway config receiver
- Remove log_level/LoggerLevel from client API
- Rewrite tg-monitor-prompts to use backend abstraction
- Update tg-dump-queues to use add_pubsub_args
Also: pubsub-abstraction.md tech spec covering problem statement,
design goals, as-is requirements, candidate broker assessment,
approach, and implementation order.
2026-04-01 20:16:53 +01:00
|
|
|
def test_response_translator_encode_with_chunks(self):
|
2026-03-09 10:53:44 +00:00
|
|
|
"""Test response translator converts Pulsar schema with chunks to dict"""
|
2025-09-02 17:58:53 +01:00
|
|
|
translator = DocumentEmbeddingsResponseTranslator()
|
2026-03-07 23:38:09 +00:00
|
|
|
|
2025-09-02 17:58:53 +01:00
|
|
|
response = DocumentEmbeddingsResponse(
|
|
|
|
|
error=None,
|
2026-03-09 10:53:44 +00:00
|
|
|
chunks=[
|
|
|
|
|
ChunkMatch(chunk_id="doc1/c1", score=0.95),
|
|
|
|
|
ChunkMatch(chunk_id="doc2/c2", score=0.85),
|
|
|
|
|
ChunkMatch(chunk_id="doc3/c3", score=0.75)
|
|
|
|
|
]
|
2025-09-02 17:58:53 +01:00
|
|
|
)
|
|
|
|
|
|
Pub/sub abstraction: decouple from Pulsar (#751)
Remove Pulsar-specific concepts from application code so that
the pub/sub backend is swappable via configuration.
Rename translators:
- to_pulsar/from_pulsar → decode/encode across all translator
classes, dispatch handlers, and tests (55+ files)
- from_response_with_completion → encode_with_completion
- Remove pulsar.schema.Record from translator base class
Queue naming (CLASS:TOPICSPACE:TOPIC):
- Replace topic() helper with queue() using new format:
flow:tg:name, request:tg:name, response:tg:name, state:tg:name
- Queue class implies persistence/TTL (no QoS in names)
- Update Pulsar backend map_topic() to parse new format
- Librarian queues use flow class (persistent, for chunking)
- Config push uses state class (persistent, last-value)
- Remove 15 dead topic imports from schema files
- Update init_trustgraph.py namespace: config → state
Confine Pulsar to pulsar_backend.py:
- Delete legacy PulsarClient class from pubsub.py
- Move add_args to add_pubsub_args() with standalone flag
for CLI tools (defaults to localhost)
- PulsarBackendConsumer.receive() catches _pulsar.Timeout,
raises standard TimeoutError
- Remove Pulsar imports from: async_processor, flow_processor,
log_level, all 11 client files, 4 storage writers, gateway
service, gateway config receiver
- Remove log_level/LoggerLevel from client API
- Rewrite tg-monitor-prompts to use backend abstraction
- Update tg-dump-queues to use add_pubsub_args
Also: pubsub-abstraction.md tech spec covering problem statement,
design goals, as-is requirements, candidate broker assessment,
approach, and implementation order.
2026-04-01 20:16:53 +01:00
|
|
|
result = translator.encode(response)
|
2026-03-07 23:38:09 +00:00
|
|
|
|
2025-09-02 17:58:53 +01:00
|
|
|
assert isinstance(result, dict)
|
2026-03-09 10:53:44 +00:00
|
|
|
assert "chunks" in result
|
|
|
|
|
assert len(result["chunks"]) == 3
|
|
|
|
|
assert result["chunks"][0]["chunk_id"] == "doc1/c1"
|
|
|
|
|
assert result["chunks"][0]["score"] == 0.95
|
2025-09-02 17:58:53 +01:00
|
|
|
|
Pub/sub abstraction: decouple from Pulsar (#751)
Remove Pulsar-specific concepts from application code so that
the pub/sub backend is swappable via configuration.
Rename translators:
- to_pulsar/from_pulsar → decode/encode across all translator
classes, dispatch handlers, and tests (55+ files)
- from_response_with_completion → encode_with_completion
- Remove pulsar.schema.Record from translator base class
Queue naming (CLASS:TOPICSPACE:TOPIC):
- Replace topic() helper with queue() using new format:
flow:tg:name, request:tg:name, response:tg:name, state:tg:name
- Queue class implies persistence/TTL (no QoS in names)
- Update Pulsar backend map_topic() to parse new format
- Librarian queues use flow class (persistent, for chunking)
- Config push uses state class (persistent, last-value)
- Remove 15 dead topic imports from schema files
- Update init_trustgraph.py namespace: config → state
Confine Pulsar to pulsar_backend.py:
- Delete legacy PulsarClient class from pubsub.py
- Move add_args to add_pubsub_args() with standalone flag
for CLI tools (defaults to localhost)
- PulsarBackendConsumer.receive() catches _pulsar.Timeout,
raises standard TimeoutError
- Remove Pulsar imports from: async_processor, flow_processor,
log_level, all 11 client files, 4 storage writers, gateway
service, gateway config receiver
- Remove log_level/LoggerLevel from client API
- Rewrite tg-monitor-prompts to use backend abstraction
- Update tg-dump-queues to use add_pubsub_args
Also: pubsub-abstraction.md tech spec covering problem statement,
design goals, as-is requirements, candidate broker assessment,
approach, and implementation order.
2026-04-01 20:16:53 +01:00
|
|
|
def test_response_translator_encode_with_empty_chunks(self):
|
2026-03-09 10:53:44 +00:00
|
|
|
"""Test response translator handles empty chunks list"""
|
2025-09-02 17:58:53 +01:00
|
|
|
translator = DocumentEmbeddingsResponseTranslator()
|
2026-03-07 23:38:09 +00:00
|
|
|
|
|
|
|
|
response = DocumentEmbeddingsResponse(
|
|
|
|
|
error=None,
|
2026-03-09 10:53:44 +00:00
|
|
|
chunks=[]
|
2026-03-07 23:38:09 +00:00
|
|
|
)
|
|
|
|
|
|
Pub/sub abstraction: decouple from Pulsar (#751)
Remove Pulsar-specific concepts from application code so that
the pub/sub backend is swappable via configuration.
Rename translators:
- to_pulsar/from_pulsar → decode/encode across all translator
classes, dispatch handlers, and tests (55+ files)
- from_response_with_completion → encode_with_completion
- Remove pulsar.schema.Record from translator base class
Queue naming (CLASS:TOPICSPACE:TOPIC):
- Replace topic() helper with queue() using new format:
flow:tg:name, request:tg:name, response:tg:name, state:tg:name
- Queue class implies persistence/TTL (no QoS in names)
- Update Pulsar backend map_topic() to parse new format
- Librarian queues use flow class (persistent, for chunking)
- Config push uses state class (persistent, last-value)
- Remove 15 dead topic imports from schema files
- Update init_trustgraph.py namespace: config → state
Confine Pulsar to pulsar_backend.py:
- Delete legacy PulsarClient class from pubsub.py
- Move add_args to add_pubsub_args() with standalone flag
for CLI tools (defaults to localhost)
- PulsarBackendConsumer.receive() catches _pulsar.Timeout,
raises standard TimeoutError
- Remove Pulsar imports from: async_processor, flow_processor,
log_level, all 11 client files, 4 storage writers, gateway
service, gateway config receiver
- Remove log_level/LoggerLevel from client API
- Rewrite tg-monitor-prompts to use backend abstraction
- Update tg-dump-queues to use add_pubsub_args
Also: pubsub-abstraction.md tech spec covering problem statement,
design goals, as-is requirements, candidate broker assessment,
approach, and implementation order.
2026-04-01 20:16:53 +01:00
|
|
|
result = translator.encode(response)
|
2026-03-07 23:38:09 +00:00
|
|
|
|
2025-09-02 17:58:53 +01:00
|
|
|
assert isinstance(result, dict)
|
2026-03-09 10:53:44 +00:00
|
|
|
assert "chunks" in result
|
|
|
|
|
assert result["chunks"] == []
|
2025-09-02 17:58:53 +01:00
|
|
|
|
Pub/sub abstraction: decouple from Pulsar (#751)
Remove Pulsar-specific concepts from application code so that
the pub/sub backend is swappable via configuration.
Rename translators:
- to_pulsar/from_pulsar → decode/encode across all translator
classes, dispatch handlers, and tests (55+ files)
- from_response_with_completion → encode_with_completion
- Remove pulsar.schema.Record from translator base class
Queue naming (CLASS:TOPICSPACE:TOPIC):
- Replace topic() helper with queue() using new format:
flow:tg:name, request:tg:name, response:tg:name, state:tg:name
- Queue class implies persistence/TTL (no QoS in names)
- Update Pulsar backend map_topic() to parse new format
- Librarian queues use flow class (persistent, for chunking)
- Config push uses state class (persistent, last-value)
- Remove 15 dead topic imports from schema files
- Update init_trustgraph.py namespace: config → state
Confine Pulsar to pulsar_backend.py:
- Delete legacy PulsarClient class from pubsub.py
- Move add_args to add_pubsub_args() with standalone flag
for CLI tools (defaults to localhost)
- PulsarBackendConsumer.receive() catches _pulsar.Timeout,
raises standard TimeoutError
- Remove Pulsar imports from: async_processor, flow_processor,
log_level, all 11 client files, 4 storage writers, gateway
service, gateway config receiver
- Remove log_level/LoggerLevel from client API
- Rewrite tg-monitor-prompts to use backend abstraction
- Update tg-dump-queues to use add_pubsub_args
Also: pubsub-abstraction.md tech spec covering problem statement,
design goals, as-is requirements, candidate broker assessment,
approach, and implementation order.
2026-04-01 20:16:53 +01:00
|
|
|
def test_response_translator_encode_with_none_chunks(self):
|
2026-03-09 10:53:44 +00:00
|
|
|
"""Test response translator handles None chunks"""
|
2025-09-02 17:58:53 +01:00
|
|
|
translator = DocumentEmbeddingsResponseTranslator()
|
2026-03-07 23:38:09 +00:00
|
|
|
|
2025-09-02 17:58:53 +01:00
|
|
|
response = MagicMock()
|
2026-03-09 10:53:44 +00:00
|
|
|
response.chunks = None
|
2026-03-07 23:38:09 +00:00
|
|
|
|
Pub/sub abstraction: decouple from Pulsar (#751)
Remove Pulsar-specific concepts from application code so that
the pub/sub backend is swappable via configuration.
Rename translators:
- to_pulsar/from_pulsar → decode/encode across all translator
classes, dispatch handlers, and tests (55+ files)
- from_response_with_completion → encode_with_completion
- Remove pulsar.schema.Record from translator base class
Queue naming (CLASS:TOPICSPACE:TOPIC):
- Replace topic() helper with queue() using new format:
flow:tg:name, request:tg:name, response:tg:name, state:tg:name
- Queue class implies persistence/TTL (no QoS in names)
- Update Pulsar backend map_topic() to parse new format
- Librarian queues use flow class (persistent, for chunking)
- Config push uses state class (persistent, last-value)
- Remove 15 dead topic imports from schema files
- Update init_trustgraph.py namespace: config → state
Confine Pulsar to pulsar_backend.py:
- Delete legacy PulsarClient class from pubsub.py
- Move add_args to add_pubsub_args() with standalone flag
for CLI tools (defaults to localhost)
- PulsarBackendConsumer.receive() catches _pulsar.Timeout,
raises standard TimeoutError
- Remove Pulsar imports from: async_processor, flow_processor,
log_level, all 11 client files, 4 storage writers, gateway
service, gateway config receiver
- Remove log_level/LoggerLevel from client API
- Rewrite tg-monitor-prompts to use backend abstraction
- Update tg-dump-queues to use add_pubsub_args
Also: pubsub-abstraction.md tech spec covering problem statement,
design goals, as-is requirements, candidate broker assessment,
approach, and implementation order.
2026-04-01 20:16:53 +01:00
|
|
|
result = translator.encode(response)
|
2026-03-07 23:38:09 +00:00
|
|
|
|
2025-09-02 17:58:53 +01:00
|
|
|
assert isinstance(result, dict)
|
2026-03-09 10:53:44 +00:00
|
|
|
assert "chunks" not in result or result.get("chunks") is None
|
2025-09-02 17:58:53 +01:00
|
|
|
|
Pub/sub abstraction: decouple from Pulsar (#751)
Remove Pulsar-specific concepts from application code so that
the pub/sub backend is swappable via configuration.
Rename translators:
- to_pulsar/from_pulsar → decode/encode across all translator
classes, dispatch handlers, and tests (55+ files)
- from_response_with_completion → encode_with_completion
- Remove pulsar.schema.Record from translator base class
Queue naming (CLASS:TOPICSPACE:TOPIC):
- Replace topic() helper with queue() using new format:
flow:tg:name, request:tg:name, response:tg:name, state:tg:name
- Queue class implies persistence/TTL (no QoS in names)
- Update Pulsar backend map_topic() to parse new format
- Librarian queues use flow class (persistent, for chunking)
- Config push uses state class (persistent, last-value)
- Remove 15 dead topic imports from schema files
- Update init_trustgraph.py namespace: config → state
Confine Pulsar to pulsar_backend.py:
- Delete legacy PulsarClient class from pubsub.py
- Move add_args to add_pubsub_args() with standalone flag
for CLI tools (defaults to localhost)
- PulsarBackendConsumer.receive() catches _pulsar.Timeout,
raises standard TimeoutError
- Remove Pulsar imports from: async_processor, flow_processor,
log_level, all 11 client files, 4 storage writers, gateway
service, gateway config receiver
- Remove log_level/LoggerLevel from client API
- Rewrite tg-monitor-prompts to use backend abstraction
- Update tg-dump-queues to use add_pubsub_args
Also: pubsub-abstraction.md tech spec covering problem statement,
design goals, as-is requirements, candidate broker assessment,
approach, and implementation order.
2026-04-01 20:16:53 +01:00
|
|
|
def test_response_translator_encode_with_completion(self):
|
2025-09-02 17:58:53 +01:00
|
|
|
"""Test response translator with completion flag"""
|
|
|
|
|
translator = DocumentEmbeddingsResponseTranslator()
|
2026-03-07 23:38:09 +00:00
|
|
|
|
2025-09-02 17:58:53 +01:00
|
|
|
response = DocumentEmbeddingsResponse(
|
|
|
|
|
error=None,
|
2026-03-09 10:53:44 +00:00
|
|
|
chunks=[
|
|
|
|
|
ChunkMatch(chunk_id="chunk1", score=0.9),
|
|
|
|
|
ChunkMatch(chunk_id="chunk2", score=0.8)
|
|
|
|
|
]
|
2025-09-02 17:58:53 +01:00
|
|
|
)
|
2026-03-07 23:38:09 +00:00
|
|
|
|
Pub/sub abstraction: decouple from Pulsar (#751)
Remove Pulsar-specific concepts from application code so that
the pub/sub backend is swappable via configuration.
Rename translators:
- to_pulsar/from_pulsar → decode/encode across all translator
classes, dispatch handlers, and tests (55+ files)
- from_response_with_completion → encode_with_completion
- Remove pulsar.schema.Record from translator base class
Queue naming (CLASS:TOPICSPACE:TOPIC):
- Replace topic() helper with queue() using new format:
flow:tg:name, request:tg:name, response:tg:name, state:tg:name
- Queue class implies persistence/TTL (no QoS in names)
- Update Pulsar backend map_topic() to parse new format
- Librarian queues use flow class (persistent, for chunking)
- Config push uses state class (persistent, last-value)
- Remove 15 dead topic imports from schema files
- Update init_trustgraph.py namespace: config → state
Confine Pulsar to pulsar_backend.py:
- Delete legacy PulsarClient class from pubsub.py
- Move add_args to add_pubsub_args() with standalone flag
for CLI tools (defaults to localhost)
- PulsarBackendConsumer.receive() catches _pulsar.Timeout,
raises standard TimeoutError
- Remove Pulsar imports from: async_processor, flow_processor,
log_level, all 11 client files, 4 storage writers, gateway
service, gateway config receiver
- Remove log_level/LoggerLevel from client API
- Rewrite tg-monitor-prompts to use backend abstraction
- Update tg-dump-queues to use add_pubsub_args
Also: pubsub-abstraction.md tech spec covering problem statement,
design goals, as-is requirements, candidate broker assessment,
approach, and implementation order.
2026-04-01 20:16:53 +01:00
|
|
|
result, is_final = translator.encode_with_completion(response)
|
2026-03-07 23:38:09 +00:00
|
|
|
|
2025-09-02 17:58:53 +01:00
|
|
|
assert isinstance(result, dict)
|
2026-03-09 10:53:44 +00:00
|
|
|
assert "chunks" in result
|
|
|
|
|
assert len(result["chunks"]) == 2
|
|
|
|
|
assert result["chunks"][0]["chunk_id"] == "chunk1"
|
2025-09-02 17:58:53 +01:00
|
|
|
assert is_final is True # Document embeddings responses are always final
|
|
|
|
|
|
Pub/sub abstraction: decouple from Pulsar (#751)
Remove Pulsar-specific concepts from application code so that
the pub/sub backend is swappable via configuration.
Rename translators:
- to_pulsar/from_pulsar → decode/encode across all translator
classes, dispatch handlers, and tests (55+ files)
- from_response_with_completion → encode_with_completion
- Remove pulsar.schema.Record from translator base class
Queue naming (CLASS:TOPICSPACE:TOPIC):
- Replace topic() helper with queue() using new format:
flow:tg:name, request:tg:name, response:tg:name, state:tg:name
- Queue class implies persistence/TTL (no QoS in names)
- Update Pulsar backend map_topic() to parse new format
- Librarian queues use flow class (persistent, for chunking)
- Config push uses state class (persistent, last-value)
- Remove 15 dead topic imports from schema files
- Update init_trustgraph.py namespace: config → state
Confine Pulsar to pulsar_backend.py:
- Delete legacy PulsarClient class from pubsub.py
- Move add_args to add_pubsub_args() with standalone flag
for CLI tools (defaults to localhost)
- PulsarBackendConsumer.receive() catches _pulsar.Timeout,
raises standard TimeoutError
- Remove Pulsar imports from: async_processor, flow_processor,
log_level, all 11 client files, 4 storage writers, gateway
service, gateway config receiver
- Remove log_level/LoggerLevel from client API
- Rewrite tg-monitor-prompts to use backend abstraction
- Update tg-dump-queues to use add_pubsub_args
Also: pubsub-abstraction.md tech spec covering problem statement,
design goals, as-is requirements, candidate broker assessment,
approach, and implementation order.
2026-04-01 20:16:53 +01:00
|
|
|
def test_response_translator_decode_not_implemented(self):
|
|
|
|
|
"""Test that decode raises NotImplementedError for responses"""
|
2025-09-02 17:58:53 +01:00
|
|
|
translator = DocumentEmbeddingsResponseTranslator()
|
2026-03-07 23:38:09 +00:00
|
|
|
|
2025-09-02 17:58:53 +01:00
|
|
|
with pytest.raises(NotImplementedError):
|
Pub/sub abstraction: decouple from Pulsar (#751)
Remove Pulsar-specific concepts from application code so that
the pub/sub backend is swappable via configuration.
Rename translators:
- to_pulsar/from_pulsar → decode/encode across all translator
classes, dispatch handlers, and tests (55+ files)
- from_response_with_completion → encode_with_completion
- Remove pulsar.schema.Record from translator base class
Queue naming (CLASS:TOPICSPACE:TOPIC):
- Replace topic() helper with queue() using new format:
flow:tg:name, request:tg:name, response:tg:name, state:tg:name
- Queue class implies persistence/TTL (no QoS in names)
- Update Pulsar backend map_topic() to parse new format
- Librarian queues use flow class (persistent, for chunking)
- Config push uses state class (persistent, last-value)
- Remove 15 dead topic imports from schema files
- Update init_trustgraph.py namespace: config → state
Confine Pulsar to pulsar_backend.py:
- Delete legacy PulsarClient class from pubsub.py
- Move add_args to add_pubsub_args() with standalone flag
for CLI tools (defaults to localhost)
- PulsarBackendConsumer.receive() catches _pulsar.Timeout,
raises standard TimeoutError
- Remove Pulsar imports from: async_processor, flow_processor,
log_level, all 11 client files, 4 storage writers, gateway
service, gateway config receiver
- Remove log_level/LoggerLevel from client API
- Rewrite tg-monitor-prompts to use backend abstraction
- Update tg-dump-queues to use add_pubsub_args
Also: pubsub-abstraction.md tech spec covering problem statement,
design goals, as-is requirements, candidate broker assessment,
approach, and implementation order.
2026-04-01 20:16:53 +01:00
|
|
|
translator.decode({"chunks": [{"chunk_id": "test", "score": 0.9}]})
|
2025-09-02 17:58:53 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
class TestDocumentEmbeddingsMessageCompatibility:
|
|
|
|
|
"""Test compatibility between request and response messages"""
|
|
|
|
|
|
|
|
|
|
def test_request_response_flow(self):
|
|
|
|
|
"""Test complete request-response flow maintains data integrity"""
|
|
|
|
|
# Create request
|
|
|
|
|
request_data = {
|
2026-03-09 10:53:44 +00:00
|
|
|
"vector": [0.1, 0.2, 0.3],
|
2025-09-02 17:58:53 +01:00
|
|
|
"limit": 5,
|
|
|
|
|
"user": "test_user",
|
|
|
|
|
"collection": "test_collection"
|
|
|
|
|
}
|
2026-03-07 23:38:09 +00:00
|
|
|
|
2025-09-02 17:58:53 +01:00
|
|
|
# Convert to Pulsar request
|
|
|
|
|
req_translator = DocumentEmbeddingsRequestTranslator()
|
Pub/sub abstraction: decouple from Pulsar (#751)
Remove Pulsar-specific concepts from application code so that
the pub/sub backend is swappable via configuration.
Rename translators:
- to_pulsar/from_pulsar → decode/encode across all translator
classes, dispatch handlers, and tests (55+ files)
- from_response_with_completion → encode_with_completion
- Remove pulsar.schema.Record from translator base class
Queue naming (CLASS:TOPICSPACE:TOPIC):
- Replace topic() helper with queue() using new format:
flow:tg:name, request:tg:name, response:tg:name, state:tg:name
- Queue class implies persistence/TTL (no QoS in names)
- Update Pulsar backend map_topic() to parse new format
- Librarian queues use flow class (persistent, for chunking)
- Config push uses state class (persistent, last-value)
- Remove 15 dead topic imports from schema files
- Update init_trustgraph.py namespace: config → state
Confine Pulsar to pulsar_backend.py:
- Delete legacy PulsarClient class from pubsub.py
- Move add_args to add_pubsub_args() with standalone flag
for CLI tools (defaults to localhost)
- PulsarBackendConsumer.receive() catches _pulsar.Timeout,
raises standard TimeoutError
- Remove Pulsar imports from: async_processor, flow_processor,
log_level, all 11 client files, 4 storage writers, gateway
service, gateway config receiver
- Remove log_level/LoggerLevel from client API
- Rewrite tg-monitor-prompts to use backend abstraction
- Update tg-dump-queues to use add_pubsub_args
Also: pubsub-abstraction.md tech spec covering problem statement,
design goals, as-is requirements, candidate broker assessment,
approach, and implementation order.
2026-04-01 20:16:53 +01:00
|
|
|
pulsar_request = req_translator.decode(request_data)
|
2026-03-07 23:38:09 +00:00
|
|
|
|
2025-09-02 17:58:53 +01:00
|
|
|
# Simulate service processing and creating response
|
|
|
|
|
response = DocumentEmbeddingsResponse(
|
|
|
|
|
error=None,
|
2026-03-09 10:53:44 +00:00
|
|
|
chunks=[
|
|
|
|
|
ChunkMatch(chunk_id="doc1/c1", score=0.95),
|
|
|
|
|
ChunkMatch(chunk_id="doc2/c2", score=0.85)
|
|
|
|
|
]
|
2025-09-02 17:58:53 +01:00
|
|
|
)
|
2026-03-07 23:38:09 +00:00
|
|
|
|
2025-09-02 17:58:53 +01:00
|
|
|
# Convert response back to dict
|
|
|
|
|
resp_translator = DocumentEmbeddingsResponseTranslator()
|
Pub/sub abstraction: decouple from Pulsar (#751)
Remove Pulsar-specific concepts from application code so that
the pub/sub backend is swappable via configuration.
Rename translators:
- to_pulsar/from_pulsar → decode/encode across all translator
classes, dispatch handlers, and tests (55+ files)
- from_response_with_completion → encode_with_completion
- Remove pulsar.schema.Record from translator base class
Queue naming (CLASS:TOPICSPACE:TOPIC):
- Replace topic() helper with queue() using new format:
flow:tg:name, request:tg:name, response:tg:name, state:tg:name
- Queue class implies persistence/TTL (no QoS in names)
- Update Pulsar backend map_topic() to parse new format
- Librarian queues use flow class (persistent, for chunking)
- Config push uses state class (persistent, last-value)
- Remove 15 dead topic imports from schema files
- Update init_trustgraph.py namespace: config → state
Confine Pulsar to pulsar_backend.py:
- Delete legacy PulsarClient class from pubsub.py
- Move add_args to add_pubsub_args() with standalone flag
for CLI tools (defaults to localhost)
- PulsarBackendConsumer.receive() catches _pulsar.Timeout,
raises standard TimeoutError
- Remove Pulsar imports from: async_processor, flow_processor,
log_level, all 11 client files, 4 storage writers, gateway
service, gateway config receiver
- Remove log_level/LoggerLevel from client API
- Rewrite tg-monitor-prompts to use backend abstraction
- Update tg-dump-queues to use add_pubsub_args
Also: pubsub-abstraction.md tech spec covering problem statement,
design goals, as-is requirements, candidate broker assessment,
approach, and implementation order.
2026-04-01 20:16:53 +01:00
|
|
|
response_data = resp_translator.encode(response)
|
2026-03-07 23:38:09 +00:00
|
|
|
|
2025-09-02 17:58:53 +01:00
|
|
|
# Verify data integrity
|
|
|
|
|
assert isinstance(pulsar_request, DocumentEmbeddingsRequest)
|
|
|
|
|
assert isinstance(response_data, dict)
|
2026-03-09 10:53:44 +00:00
|
|
|
assert "chunks" in response_data
|
|
|
|
|
assert len(response_data["chunks"]) == 2
|
2025-09-02 17:58:53 +01:00
|
|
|
|
|
|
|
|
def test_error_response_flow(self):
|
|
|
|
|
"""Test error response flow"""
|
|
|
|
|
# Create error response
|
|
|
|
|
error = Error(
|
|
|
|
|
type="vector_db_error",
|
|
|
|
|
message="Collection not found"
|
|
|
|
|
)
|
2026-03-07 23:38:09 +00:00
|
|
|
|
2025-09-02 17:58:53 +01:00
|
|
|
response = DocumentEmbeddingsResponse(
|
|
|
|
|
error=error,
|
2026-03-09 10:53:44 +00:00
|
|
|
chunks=[]
|
2025-09-02 17:58:53 +01:00
|
|
|
)
|
2026-03-07 23:38:09 +00:00
|
|
|
|
2025-09-02 17:58:53 +01:00
|
|
|
# Convert response to dict
|
|
|
|
|
translator = DocumentEmbeddingsResponseTranslator()
|
Pub/sub abstraction: decouple from Pulsar (#751)
Remove Pulsar-specific concepts from application code so that
the pub/sub backend is swappable via configuration.
Rename translators:
- to_pulsar/from_pulsar → decode/encode across all translator
classes, dispatch handlers, and tests (55+ files)
- from_response_with_completion → encode_with_completion
- Remove pulsar.schema.Record from translator base class
Queue naming (CLASS:TOPICSPACE:TOPIC):
- Replace topic() helper with queue() using new format:
flow:tg:name, request:tg:name, response:tg:name, state:tg:name
- Queue class implies persistence/TTL (no QoS in names)
- Update Pulsar backend map_topic() to parse new format
- Librarian queues use flow class (persistent, for chunking)
- Config push uses state class (persistent, last-value)
- Remove 15 dead topic imports from schema files
- Update init_trustgraph.py namespace: config → state
Confine Pulsar to pulsar_backend.py:
- Delete legacy PulsarClient class from pubsub.py
- Move add_args to add_pubsub_args() with standalone flag
for CLI tools (defaults to localhost)
- PulsarBackendConsumer.receive() catches _pulsar.Timeout,
raises standard TimeoutError
- Remove Pulsar imports from: async_processor, flow_processor,
log_level, all 11 client files, 4 storage writers, gateway
service, gateway config receiver
- Remove log_level/LoggerLevel from client API
- Rewrite tg-monitor-prompts to use backend abstraction
- Update tg-dump-queues to use add_pubsub_args
Also: pubsub-abstraction.md tech spec covering problem statement,
design goals, as-is requirements, candidate broker assessment,
approach, and implementation order.
2026-04-01 20:16:53 +01:00
|
|
|
response_data = translator.encode(response)
|
2026-03-07 23:38:09 +00:00
|
|
|
|
2025-09-02 17:58:53 +01:00
|
|
|
# Verify error handling
|
|
|
|
|
assert isinstance(response_data, dict)
|
2026-03-09 10:53:44 +00:00
|
|
|
# The translator doesn't include error in the dict, only chunks
|
|
|
|
|
assert "chunks" in response_data
|
|
|
|
|
assert response_data["chunks"] == []
|