Files
wehub-resource-sync dc6079821b
CI Github Actions / Run Tests (push) Waiting to run
Automatic PR Merger / mergepal (push) Waiting to run
Semgrep / Semgrep Workflow Security Scan (push) Waiting to run
Docs Tests / Check for file changes (push) Has been cancelled
Docs Tests / Test Documentation (push) Has been cancelled
Docs Tests / Documentation Linting Checks (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.10, test-performance) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.10, test-policies) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.8, test-cli) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.8, test-core-featurizers) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.8, test-full-model-training) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.8, test-nlu-featurizers) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.8, test-nlu-predictors) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.8, test-other-unit-tests) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.8, test-performance) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.8, test-policies) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.9, test-cli) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.9, test-core-featurizers) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.9, test-full-model-training) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.9, test-nlu-featurizers) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.9, test-nlu-predictors) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.9, test-other-unit-tests) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.9, test-performance) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.9, test-policies) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.10, test-cli) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.10, test-core-featurizers) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.10, test-full-model-training) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.10, test-nlu-featurizers) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.10, test-nlu-predictors) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.10, test-other-unit-tests) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.10, test-performance) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.10, test-policies) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.8, test-cli) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.8, test-core-featurizers) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.8, test-full-model-training) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.8, test-nlu-featurizers) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.8, test-nlu-predictors) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.8, test-other-unit-tests) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.8, test-performance) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.8, test-policies) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.9, test-cli) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.9, test-core-featurizers) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.9, test-full-model-training) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.9, test-nlu-featurizers) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.9, test-nlu-predictors) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.9, test-other-unit-tests) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.9, test-performance) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.9, test-policies) (push) Has been cancelled
Continuous Integration / Run Flaky Tests (ubuntu-24.04, 3.10) (push) Has been cancelled
Continuous Integration / Run Flaky Tests (ubuntu-24.04, 3.8) (push) Has been cancelled
Continuous Integration / Run Flaky Tests (ubuntu-24.04, 3.9) (push) Has been cancelled
Continuous Integration / Run Flaky Tests (windows-2022, 3.10) (push) Has been cancelled
Continuous Integration / Run Flaky Tests (windows-2022, 3.8) (push) Has been cancelled
Continuous Integration / Run Flaky Tests (windows-2022, 3.9) (push) Has been cancelled
Continuous Integration / Check for file changes (push) Has been cancelled
Continuous Integration / Wait for docs tests (push) Has been cancelled
Continuous Integration / Code Quality (push) Has been cancelled
Continuous Integration / Check for changelog (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.10, test-cli) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.10, test-core-featurizers) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.10, test-full-model-training) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.10, test-nlu-featurizers) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.10, test-nlu-predictors) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.10, test-other-unit-tests) (push) Has been cancelled
Continuous Integration / Upload coverage reports to codeclimate (push) Has been cancelled
Continuous Integration / Run Non-Sequential Integration Tests (push) Has been cancelled
Continuous Integration / Run Broker Integration Tests (push) Has been cancelled
Continuous Integration / Run Sequential Integration Tests (push) Has been cancelled
Continuous Integration / Build Docker base images and setup environment (push) Has been cancelled
Continuous Integration / Build Docker (default) (push) Has been cancelled
Continuous Integration / Build Docker (full) (push) Has been cancelled
Continuous Integration / Build Docker (mitie-en) (push) Has been cancelled
Continuous Integration / Build Docker (spacy-de) (push) Has been cancelled
Continuous Integration / Build Docker (spacy-en) (push) Has been cancelled
Continuous Integration / Build Docker (spacy-it) (push) Has been cancelled
Continuous Integration / Deploy to PyPI (push) Has been cancelled
Continuous Integration / Notify Slack & Publish Release Notes (push) Has been cancelled
Publish Documentation / Evaluate release tag (push) Has been cancelled
Publish Documentation / Prebuild Docs (push) Has been cancelled
Publish Documentation / Preview Docs (push) Has been cancelled
Publish Documentation / Check for file changes (push) Has been cancelled
Publish Documentation / Publish Docs (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:24:47 +08:00

323 lines
11 KiB
Python

import uuid
from pathlib import Path
from typing import Any, AsyncIterator, Dict, Optional, Text, List
from unittest.mock import Mock
import pytest
from rasa.shared.core.constants import ACTION_SESSION_START_NAME
from rasa.shared.core.domain import Domain
from rasa.core.brokers.pika import PikaEventBroker
from rasa.core.brokers.sql import SQLEventBroker
from rasa.core.constants import RASA_EXPORT_PROCESS_ID_HEADER_NAME
from rasa.shared.core.events import Event, SessionStarted, ActionExecuted
from rasa.core.tracker_store import SQLTrackerStore
from rasa.shared.core.trackers import DialogueStateTracker
from rasa.exceptions import (
NoConversationsInTrackerStoreError,
NoEventsToMigrateError,
PublishingError,
)
from tests.conftest import MockExporter, random_user_uttered_event, AsyncMock
@pytest.mark.parametrize(
"requested_ids,available_ids,expected",
[(["1"], ["1"], ["1"]), (["1", "2"], ["2"], ["2"]), (None, ["2"], ["2"])],
)
async def test_get_conversation_ids_to_process(
requested_ids: Optional[List[Text]],
available_ids: Optional[List[Text]],
expected: Optional[List[Text]],
):
# create and mock tracker store containing `available_ids` as keys
tracker_store = Mock()
tracker_store.keys = AsyncMock(return_value=available_ids)
exporter = MockExporter(tracker_store)
exporter.requested_conversation_ids = requested_ids
# noinspection PyProtectedMember
assert await exporter._get_conversation_ids_to_process() == set(expected)
@pytest.mark.parametrize(
"requested_ids,available_ids,exception",
[
(["1"], [], NoConversationsInTrackerStoreError), # no IDs in tracker store
(None, [], NoConversationsInTrackerStoreError), # without requested IDs
(
["1", "2", "3"],
["4", "5", "6"],
NoEventsToMigrateError,
), # no overlap between requested IDs and those available
],
)
async def test_get_conversation_ids_to_process_error(
requested_ids: Optional[List[Text]], available_ids: List[Text], exception: Exception
):
# create and mock tracker store containing `available_ids` as keys
tracker_store = Mock()
tracker_store.keys = AsyncMock(return_value=available_ids)
exporter = MockExporter(tracker_store)
exporter.requested_conversation_ids = requested_ids
with pytest.raises(exception):
# noinspection PyProtectedMember
await exporter._get_conversation_ids_to_process()
async def test_fetch_events_within_time_range():
conversation_ids = ["some-id", "another-id"]
# prepare events from different senders and different timestamps
event_1 = random_user_uttered_event(1)
event_2 = random_user_uttered_event(3)
event_3 = random_user_uttered_event(2)
events = {conversation_ids[0]: [event_1, event_2], conversation_ids[1]: [event_3]}
def _get_tracker(conversation_id: Text) -> DialogueStateTracker:
return DialogueStateTracker.from_events(
conversation_id, events[conversation_id]
)
# create mock tracker store
tracker_store = AsyncMock()
tracker_store.retrieve_full_tracker.side_effect = _get_tracker
tracker_store.keys = AsyncMock(return_value=conversation_ids)
exporter = MockExporter(tracker_store)
exporter.requested_conversation_ids = conversation_ids
# noinspection PyProtectedMember
fetched_events = [e async for e in exporter._fetch_events_within_time_range()]
# events should come back for all requested conversation IDs
assert all(
any(_id in event["sender_id"] for event in fetched_events)
for _id in conversation_ids
)
for _id in conversation_ids:
# events are sorted by timestamp
event_timestamps = [
e["timestamp"] for e in fetched_events if e["sender_id"] == _id
]
assert event_timestamps == [e.timestamp for e in events[_id]]
async def test_fetch_events_within_time_range_tracker_does_not_err():
# create mock tracker store that returns `None` on `retrieve_full_tracker()`
tracker_store = Mock()
tracker_store.keys = AsyncMock(return_value=[uuid.uuid4()])
tracker_store.retrieve_full_tracker = AsyncMock(return_value=None)
exporter = MockExporter(tracker_store)
assert not [e async for e in exporter._fetch_events_within_time_range()]
async def test_fetch_events_within_time_range_tracker_contains_no_events():
# create mock tracker store that returns `None` on `retrieve_full_tracker()`
tracker_store = Mock()
tracker_store.keys = AsyncMock(return_value=["a great ID"])
tracker_store.retrieve_full_tracker = AsyncMock(
return_value=DialogueStateTracker.from_events("a great ID", [])
)
exporter = MockExporter(tracker_store)
assert not [e async for e in exporter._fetch_events_within_time_range()]
async def mock_tracker_store(
events: Dict[Text, List[Event]], tmp_path: Path
) -> DialogueStateTracker:
tracker_store = SQLTrackerStore(
dialect="sqlite",
db=str(tmp_path / f"{uuid.uuid4().hex}.db"),
domain=Domain.empty(),
)
for conversation_id, conversation_events in events.items():
tracker = DialogueStateTracker.from_events(
conversation_id, evts=conversation_events
)
await tracker_store.save(tracker)
return tracker_store
async def test_fetch_events_within_time_range_with_session_events(tmp_path: Path):
conversation_id = "test_fetch_events_within_time_range_with_sessions"
events = {
conversation_id: [
random_user_uttered_event(1),
SessionStarted(2),
ActionExecuted(timestamp=3, action_name=ACTION_SESSION_START_NAME),
random_user_uttered_event(4),
]
}
tracker_store = await mock_tracker_store(events, tmp_path)
exporter = MockExporter(tracker_store=tracker_store)
# noinspection PyProtectedMember
fetched_events = [e async for e in exporter._fetch_events_within_time_range()]
assert len(fetched_events) == len(events[conversation_id])
# noinspection PyProtectedMember
async def test_sort_and_select_events_by_timestamp(tmp_path: Path):
conversation_id = "test_sort_and_select_events_by_timestamp"
conversations = {
conversation_id: [
random_user_uttered_event(3),
random_user_uttered_event(2),
random_user_uttered_event(1),
]
}
tracker_store = await mock_tracker_store(conversations, tmp_path)
exporter = MockExporter(tracker_store)
event_ts = [e.timestamp for e in conversations[conversation_id]]
selected_events = [e async for e in exporter._fetch_events_within_time_range()]
# events are sorted
assert selected_events == list(
sorted(selected_events, key=lambda e: e["timestamp"])
)
# apply minimum timestamp requirement, expect to get only two events back
exporter.minimum_timestamp = 2.0
selected_events = [e async for e in exporter._fetch_events_within_time_range()]
assert [e["timestamp"] for e in selected_events] == [
event_ts[1],
event_ts[0],
]
exporter.minimum_timestamp = None
# apply maximum timestamp requirement, expect to get only one
exporter.maximum_timestamp = 1.1
selected_events = [e async for e in exporter._fetch_events_within_time_range()]
assert [e["timestamp"] for e in selected_events] == [event_ts[2]]
# apply both requirements, get one event back
exporter.minimum_timestamp = 2.0
exporter.maximum_timestamp = 2.1
selected_events = [e async for e in exporter._fetch_events_within_time_range()]
assert [e["timestamp"] for e in selected_events] == [event_ts[1]]
# noinspection PyProtectedMember
async def test_sort_and_select_events_by_timestamp_error(tmp_path: Path):
conversation_id = "test_sort_and_select_events_by_timestamp_error"
conversations = {
conversation_id: [
random_user_uttered_event(3),
]
}
tracker_store = await mock_tracker_store(conversations, tmp_path)
exporter = MockExporter(tracker_store)
# supply list of events, apply timestamp constraint and no events survive
exporter.minimum_timestamp = 3.1
assert not [e async for e in exporter._fetch_events_within_time_range()]
def test_get_message_headers_pika_event_broker():
event_broker = Mock(spec=PikaEventBroker)
exporter = MockExporter(event_broker=event_broker)
# noinspection PyProtectedMember
headers = exporter._get_message_headers()
assert headers.get(RASA_EXPORT_PROCESS_ID_HEADER_NAME)
def test_get_message_headers_non_pika_broker():
event_broker = Mock()
exporter = MockExporter(event_broker=event_broker)
# noinspection PyProtectedMember
assert exporter._get_message_headers() is None
def test_publish_with_headers_pika_event_broker():
event_broker = Mock(spec=PikaEventBroker)
exporter = MockExporter(event_broker=event_broker)
headers = {"some": "header"}
event = {"some": "event"}
# noinspection PyProtectedMember
exporter._publish_with_message_headers(event, headers)
# the `PikaEventBroker`'s `publish()` method was called with both
# the `event` and `headers` arguments
event_broker.publish.assert_called_with(event=event, headers=headers)
def test_publish_with_headers_non_pika_event_broker():
event_broker = Mock(SQLEventBroker)
exporter = MockExporter(event_broker=event_broker)
headers = {"some": "header"}
event = {"some": "event"}
# noinspection PyProtectedMember
exporter._publish_with_message_headers(event, headers)
# the `SQLEventBroker`'s `publish()` method was called with only the `event`
# argument
event_broker.publish.assert_called_with(event)
async def test_publishing_error():
# mock event broker so it raises on `publish()`
event_broker = Mock()
event_broker.publish.side_effect = ValueError()
exporter = MockExporter(event_broker=event_broker)
user_event = random_user_uttered_event(1).as_dict()
user_event["sender_id"] = uuid.uuid4().hex
async def _mocked_fetch() -> AsyncIterator[Dict[Text, Any]]:
yield user_event
# noinspection PyProtectedMember
exporter._fetch_events_within_time_range = _mocked_fetch
# run the export function
with pytest.raises(PublishingError):
await exporter.publish_events()
async def test_closing_broker():
exporter = MockExporter(event_broker=SQLEventBroker())
# noinspection PyProtectedMember
async def _mocked_fetch() -> AsyncIterator[Dict[Text, Any]]:
# need an async generator that is empty
if False:
yield
return
# noinspection PyProtectedMember
exporter._fetch_events_within_time_range = _mocked_fetch
# run the export function
with pytest.warns(None) as warnings:
await exporter.publish_events()
assert len(warnings) == 0