| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392 |
- # -*- coding: utf-8 -*-
- """
- Unit-Tests für trixy_core.events.
- """
- import pytest
- from unittest.mock import MagicMock, AsyncMock
- from datetime import datetime
- from trixy_core.events.enums import EventPriority
- from trixy_core.events.event_data.base import EventData
- from trixy_core.events.event_data.basic import (
- SatelliteConnected, SatelliteDisconnected, MusicSocketConnected,
- WakewordReceived, RawAudioInputReceived,
- SpeechRecognized, IntentReceived,
- ConversationStarted, ConversationEnded,
- PluginLoaded, PluginUnloaded, SystemShutdown
- )
- from trixy_core.events.decorators import TrixyEvent, event_handler, get_event_handlers
- from trixy_core.events.eventmanager import EventManager
- class TestEventPriority:
- """Tests für EventPriority."""
- def test_priority_ordering(self):
- """Testet die Prioritätsreihenfolge."""
- assert EventPriority.SYSTEM < EventPriority.HIGHEST
- assert EventPriority.HIGHEST < EventPriority.HIGH
- assert EventPriority.HIGH < EventPriority.NORMAL
- assert EventPriority.NORMAL < EventPriority.LOW
- assert EventPriority.LOW < EventPriority.LOWEST
- assert EventPriority.LOWEST < EventPriority.MONITOR
- def test_priority_values(self):
- """Testet die Prioritätswerte."""
- assert EventPriority.SYSTEM == 0
- assert EventPriority.NORMAL == 30
- assert EventPriority.MONITOR == 100
- class TestEventData:
- """Tests für EventData-Basisklasse."""
- def test_event_data_creation(self):
- """Testet die Event-Data-Erstellung."""
- event = EventData()
- assert event.event_id is not None
- assert isinstance(event.timestamp, datetime)
- assert event.source == ""
- assert event.cancelled is False
- def test_event_data_cancel(self):
- """Testet das Abbrechen eines Events."""
- event = EventData()
- assert event.is_cancelled() is False
- event.cancel()
- assert event.is_cancelled() is True
- def test_event_name_snake_case(self):
- """Testet die Event-Name-Konvertierung."""
- assert EventData.event_name() == "event_data"
- def test_custom_source(self):
- """Testet benutzerdefinierte Quelle."""
- event = EventData(source="TestSource")
- assert event.source == "TestSource"
- def test_metadata(self):
- """Testet Metadaten."""
- event = EventData(metadata={"key": "value"})
- assert event.metadata == {"key": "value"}
- class TestBasicEventData:
- """Tests für grundlegende Event-Datenklassen."""
- def test_satellite_connected(self):
- """Testet SatelliteConnected."""
- event = SatelliteConnected(
- satellite_id="sat-1",
- room="wohnzimmer",
- alias="Echo 1",
- mac_address="AA:BB:CC:DD:EE:FF",
- ip_address="192.168.1.100"
- )
- assert event.satellite_id == "sat-1"
- assert event.room == "wohnzimmer"
- assert event.alias == "Echo 1"
- assert SatelliteConnected.event_name() == "satellite_connected"
- def test_satellite_disconnected(self):
- """Testet SatelliteDisconnected."""
- event = SatelliteDisconnected(
- satellite_id="sat-1",
- reason="Connection lost"
- )
- assert event.satellite_id == "sat-1"
- assert event.reason == "Connection lost"
- def test_music_socket_connected(self):
- """Testet MusicSocketConnected."""
- event = MusicSocketConnected(
- satellite_id="sat-1",
- alias="Echo 1",
- room="wohnzimmer"
- )
- assert event.satellite_id == "sat-1"
- assert event.alias == "Echo 1"
- assert event.room == "wohnzimmer"
- assert MusicSocketConnected.event_name() == "music_socket_connected"
- def test_wakeword_received(self):
- """Testet WakewordReceived."""
- event = WakewordReceived(
- satellite_id="sat-1",
- wakeword_model="custom",
- confidence=0.95,
- audio_level=0.7
- )
- assert event.confidence == 0.95
- assert event.audio_level == 0.7
- assert WakewordReceived.event_name() == "wakeword_received"
- def test_raw_audio_input_received(self):
- """Testet RawAudioInputReceived."""
- audio = b"\x00\x00" * 100
- event = RawAudioInputReceived(
- audio_data=audio,
- sample_rate=16000,
- duration_seconds=1.0
- )
- assert event.audio_data == audio
- assert event.sample_rate == 16000
- def test_speech_recognized(self):
- """Testet SpeechRecognized."""
- event = SpeechRecognized(
- text="Hallo Trixy",
- confidence=0.98,
- language="de"
- )
- assert event.text == "Hallo Trixy"
- assert event.language == "de"
- def test_intent_received(self):
- """Testet IntentReceived."""
- event = IntentReceived(
- intent="turn_on_light",
- confidence=0.9,
- slots={"room": "wohnzimmer"}
- )
- assert event.intent == "turn_on_light"
- assert event.slots["room"] == "wohnzimmer"
- def test_conversation_started(self):
- """Testet ConversationStarted."""
- event = ConversationStarted(
- satellite_id="sat-1",
- conversation_id="conv-123"
- )
- assert event.conversation_id == "conv-123"
- def test_conversation_ended(self):
- """Testet ConversationEnded."""
- event = ConversationEnded(
- conversation_id="conv-123",
- reason="completed"
- )
- assert event.reason == "completed"
- def test_plugin_loaded(self):
- """Testet PluginLoaded."""
- event = PluginLoaded(
- plugin_name="TestPlugin",
- plugin_version="1.0.0"
- )
- assert event.plugin_name == "TestPlugin"
- def test_system_shutdown(self):
- """Testet SystemShutdown."""
- event = SystemShutdown(
- reason="User request",
- force=True
- )
- assert event.reason == "User request"
- assert event.force is True
- class TestEventDecorators:
- """Tests für Event-Dekoratoren."""
- def test_trixy_event_decorator(self):
- """Testet den TrixyEvent-Dekorator."""
- class TestHandler:
- @TrixyEvent(["wakeword_received", "satellite_connected"])
- def on_events(self, event_name, event_data):
- pass
- handlers = get_event_handlers(TestHandler())
- assert len(handlers) == 2
- event_names = [h["event_name"] for h in handlers]
- assert "wakeword_received" in event_names
- assert "satellite_connected" in event_names
- def test_trixy_event_with_priority(self):
- """Testet TrixyEvent mit Priorität."""
- class TestHandler:
- @TrixyEvent(["test_event"], priority=EventPriority.HIGH)
- def on_event(self, event_name, event_data):
- pass
- handlers = get_event_handlers(TestHandler())
- assert len(handlers) == 1
- assert handlers[0]["priority"] == EventPriority.HIGH
- def test_event_handler_decorator(self):
- """Testet den event_handler-Dekorator."""
- class TestHandler:
- @event_handler(WakewordReceived)
- async def on_wakeword(self, event):
- pass
- handlers = get_event_handlers(TestHandler())
- assert len(handlers) == 1
- assert handlers[0]["event_name"] == "wakeword_received"
- assert handlers[0]["event_class"] == WakewordReceived
- class TestEventManager:
- """Tests für EventManager."""
- @pytest.fixture
- def mock_application(self):
- """Erstellt eine Mock-Anwendung."""
- return MagicMock()
- @pytest.fixture
- def manager(self, mock_application):
- """Erstellt einen EventManager."""
- return EventManager(mock_application)
- def test_manager_initialization(self, manager):
- """Testet die Manager-Initialisierung."""
- assert manager._handlers == {}
- assert manager._global_handlers == []
- def test_register_handler(self, manager):
- """Testet die Handler-Registrierung."""
- def handler(event_name, event_data):
- pass
- manager.register("test_event", handler)
- assert manager.has_handlers("test_event")
- def test_unregister_handler(self, manager):
- """Testet die Handler-Deregistrierung."""
- def handler(event_name, event_data):
- pass
- manager.register("test_event", handler)
- result = manager.unregister("test_event", handler)
- assert result is True
- assert not manager.has_handlers("test_event")
- def test_register_global_handler(self, manager):
- """Testet die globale Handler-Registrierung."""
- def handler(event_name, event_data):
- pass
- manager.register_global(handler)
- assert len(manager._global_handlers) == 1
- @pytest.mark.asyncio
- async def test_trigger_event(self, manager):
- """Testet das Auslösen eines Events."""
- called = []
- def handler(event_name, event_data):
- called.append((event_name, event_data))
- manager.register("test_event", handler)
- event_data = EventData()
- result = await manager.trigger("test_event", event_data)
- assert len(called) == 1
- assert called[0][0] == "test_event"
- assert called[0][1] == event_data
- @pytest.mark.asyncio
- async def test_trigger_async_handler(self, manager):
- """Testet das Auslösen mit async Handler."""
- called = []
- async def async_handler(event_name, event_data):
- called.append(event_name)
- manager.register("async_event", async_handler)
- await manager.trigger("async_event", EventData())
- assert "async_event" in called
- @pytest.mark.asyncio
- async def test_event_cancellation(self, manager):
- """Testet die Event-Abbruchfunktion."""
- order = []
- def first_handler(event_name, event_data):
- order.append("first")
- event_data.cancel()
- def second_handler(event_name, event_data):
- order.append("second")
- manager.register("cancel_test", first_handler, EventPriority.HIGH)
- manager.register("cancel_test", second_handler, EventPriority.NORMAL)
- event = EventData()
- await manager.trigger("cancel_test", event)
- assert "first" in order
- assert "second" not in order # Wurde abgebrochen
- @pytest.mark.asyncio
- async def test_monitor_receives_cancelled_events(self, manager):
- """Testet, dass MONITOR-Handler abgebrochene Events erhalten."""
- received = []
- def canceller(event_name, event_data):
- event_data.cancel()
- def monitor(event_name, event_data):
- received.append(event_name)
- manager.register("monitor_test", canceller, EventPriority.HIGH)
- manager.register("monitor_test", monitor, EventPriority.MONITOR)
- await manager.trigger("monitor_test", EventData())
- assert "monitor_test" in received
- @pytest.mark.asyncio
- async def test_priority_ordering(self, manager):
- """Testet die Prioritätsreihenfolge."""
- order = []
- def low_handler(event_name, event_data):
- order.append("low")
- def high_handler(event_name, event_data):
- order.append("high")
- manager.register("priority_test", low_handler, EventPriority.LOW)
- manager.register("priority_test", high_handler, EventPriority.HIGH)
- await manager.trigger("priority_test", EventData())
- assert order == ["high", "low"]
- def test_get_registered_events(self, manager):
- """Testet das Abrufen registrierter Events."""
- manager.register("event1", lambda *args: None)
- manager.register("event2", lambda *args: None)
- events = manager.get_registered_events()
- assert "event1" in events
- assert "event2" in events
- def test_clear_all(self, manager):
- """Testet das Löschen aller Handler."""
- manager.register("event1", lambda *args: None)
- manager.register_global(lambda *args: None)
- manager.clear_all()
- assert manager._handlers == {}
- assert manager._global_handlers == []
- def test_register_object(self, manager):
- """Testet die Registrierung eines Objekts."""
- class Handler:
- @TrixyEvent(["test_event"])
- def on_test(self, event_name, event_data):
- pass
- handler = Handler()
- manager.register_object(handler)
- assert manager.has_handlers("test_event")
|