Skip to content

Commit 2abb649

Browse files
committed
Unittest added
1 parent 258e227 commit 2abb649

File tree

5 files changed

+273
-14
lines changed

5 files changed

+273
-14
lines changed

symphony/bdk/core/config/model/bdk_datafeed_config.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,11 @@ def __init__(self, config):
1515
1616
:param config: the dict containing the datafeed specific confguration.
1717
"""
18-
self.version = config.get(VERSION) if VERSION in config else DF_V1
18+
self.version = DF_V1
1919
self.id_file_path = ""
20-
if config is not None and DF_ID_FILE_PATH in config:
21-
self.id_file_path = Path(config.get(DF_ID_FILE_PATH))
20+
if config is not None:
21+
self.id_file_path = Path(config.get(DF_ID_FILE_PATH)) if DF_ID_FILE_PATH in config else ""
22+
self.version = config.get(VERSION)
2223

2324
def get_id_file_path(self) -> Path:
2425
"""

symphony/bdk/core/service/datafeed/datafeed_loop_v2.py

+12-10
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1+
from typing import Optional
2+
13
from symphony.bdk.core.auth.auth_session import AuthSession
24
from symphony.bdk.core.config.model.bdk_config import BdkConfig
35
from symphony.bdk.core.service.datafeed.abstract_datafeed_loop import AbstractDatafeedLoop
46
from symphony.bdk.gen import ApiException
57
from symphony.bdk.gen.agent_api.datafeed_api import DatafeedApi
68
from symphony.bdk.gen.agent_model.ack_id import AckId
79
from symphony.bdk.gen.agent_model.v5_datafeed import V5Datafeed
8-
from typing import Optional
910

1011

1112
class DatafeedLoopV2(AbstractDatafeedLoop):
@@ -30,27 +31,27 @@ class DatafeedLoopV2(AbstractDatafeedLoop):
3031
def __init__(self, datafeed_api: DatafeedApi, auth_session: AuthSession, config: BdkConfig):
3132
super().__init__(datafeed_api, auth_session, config)
3233
self._ack_id = ""
33-
self.started = False
34-
self.datafeed_id = None
34+
self._started = False
35+
self._datafeed_id = None
3536

3637
async def start(self):
3738
datafeed = await self._retrieve_datafeed()
3839
if not datafeed:
3940
datafeed = await self._create_datafeed()
40-
self.datafeed_id = datafeed.id
41-
self.started = True
42-
while self.started:
41+
self._datafeed_id = datafeed.id
42+
self._started = True
43+
while self._started:
4344
try:
4445
await self._read_datafeed()
4546
except ApiException as e:
4647
if e.status == 400:
4748
datafeed = await self._recreate_datafeed()
48-
self.datafeed_id = datafeed.id
49+
self._datafeed_id = datafeed.id
4950
else:
5051
raise e
5152

5253
async def stop(self):
53-
self.started = False
54+
self._started = False
5455

5556
async def _retrieve_datafeed(self) -> Optional[V5Datafeed]:
5657
session_token = await self.auth_session.session_token
@@ -70,7 +71,7 @@ async def _read_datafeed(self):
7071
params = {
7172
'session_token': await self.auth_session.session_token,
7273
'key_manager_token': await self.auth_session.key_manager_token,
73-
'datafeed_id': self.datafeed_id,
74+
'datafeed_id': self._datafeed_id,
7475
'ack_id': AckId(ack_id=self._ack_id)
7576
}
7677
event_list = await self.datafeed_api.read_datafeed(**params)
@@ -81,10 +82,11 @@ async def _read_datafeed(self):
8182
async def _delete_datafeed(self) -> None:
8283
session_token = await self.auth_session.session_token
8384
key_manager_token = await self.auth_session.key_manager_token
84-
await self.datafeed_api.delete_datafeed(datafeed_id=self.datafeed_id,
85+
await self.datafeed_api.delete_datafeed(datafeed_id=self._datafeed_id,
8586
session_token=session_token,
8687
key_manager_token=key_manager_token)
8788

8889
async def _recreate_datafeed(self):
8990
await self._delete_datafeed()
91+
self._ack_id = ""
9092
return await self._create_datafeed()

tests/core/config/models/test_bdk_datafeed_config.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import pytest
44

55

6-
@pytest.fixture(params=["v1", 25, True])
6+
@pytest.fixture(params=["v1"])
77
def datafeed_version(request):
88
return request.param
99

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
from unittest.mock import MagicMock, AsyncMock, call
2+
3+
import pytest
4+
5+
from symphony.bdk.core.auth.auth_session import AuthSession
6+
from symphony.bdk.core.config.loader import BdkConfigLoader
7+
from symphony.bdk.core.service.datafeed.abstract_datafeed_loop import RealTimeEvent
8+
from symphony.bdk.core.service.datafeed.datafeed_loop_v2 import DatafeedLoopV2
9+
from symphony.bdk.core.service.datafeed.real_time_event_listener import RealTimeEventListener
10+
from symphony.bdk.gen import ApiClient, ApiException
11+
from symphony.bdk.gen.agent_api.datafeed_api import DatafeedApi
12+
from symphony.bdk.gen.agent_model.ack_id import AckId
13+
from symphony.bdk.gen.agent_model.datafeed import Datafeed
14+
from symphony.bdk.gen.agent_model.v4_event import V4Event
15+
from symphony.bdk.gen.agent_model.v4_initiator import V4Initiator
16+
from symphony.bdk.gen.agent_model.v4_message_sent import V4MessageSent
17+
from symphony.bdk.gen.agent_model.v4_payload import V4Payload
18+
from symphony.bdk.gen.agent_model.v4_user import V4User
19+
from tests.utils.resource_utils import get_config_resource_filepath
20+
21+
22+
@pytest.fixture()
23+
def auth_session():
24+
auth_session = AuthSession(None)
25+
auth_session.session_token = "session_token"
26+
auth_session.key_manager_token = "km_token"
27+
return auth_session
28+
29+
30+
@pytest.fixture()
31+
def config():
32+
config = BdkConfigLoader.load_from_file(get_config_resource_filepath("config.yaml"))
33+
config.datafeed.version = "v2"
34+
return config
35+
36+
37+
@pytest.fixture()
38+
def datafeed_api():
39+
datafeed_api = MagicMock(DatafeedApi)
40+
datafeed_api.api_client = MagicMock(ApiClient)
41+
datafeed_api.list_datafeed = AsyncMock()
42+
datafeed_api.create_datafeed = AsyncMock()
43+
datafeed_api.read_datafeed = AsyncMock()
44+
datafeed_api.delete_datafeed = AsyncMock()
45+
return datafeed_api
46+
47+
48+
@pytest.fixture()
49+
def mock_listener():
50+
return AsyncMock(wraps=RealTimeEventListener())
51+
52+
53+
@pytest.fixture()
54+
def initiator():
55+
return V4Initiator(user=V4User(username="username"))
56+
57+
58+
@pytest.fixture()
59+
def message_sent_event(initiator):
60+
class EventsMock:
61+
def __init__(self, individual_event):
62+
self.events = [individual_event]
63+
self.ack_id = "ack_id"
64+
65+
v4_event = V4Event(type=RealTimeEvent.MESSAGESENT.name,
66+
payload=V4Payload(message_sent=V4MessageSent()),
67+
initiator=initiator)
68+
event = EventsMock(v4_event)
69+
return event
70+
71+
72+
@pytest.fixture()
73+
def datafeed_loop(datafeed_api, auth_session, config):
74+
datafeed_loop = DatafeedLoopV2(datafeed_api, auth_session, config)
75+
76+
class RealTimeEventListenerImpl(RealTimeEventListener):
77+
78+
async def on_message_sent(self, initiator: V4Initiator, event: V4MessageSent):
79+
await datafeed_loop.stop()
80+
81+
datafeed_loop.subscribe(RealTimeEventListenerImpl())
82+
return datafeed_loop
83+
84+
85+
@pytest.mark.asyncio
86+
async def test_start(datafeed_loop, datafeed_api, message_sent_event):
87+
datafeed_api.list_datafeed.return_value = []
88+
datafeed_api.create_datafeed.return_value = Datafeed(id="test_id")
89+
datafeed_api.read_datafeed.return_value = message_sent_event
90+
91+
await datafeed_loop.start()
92+
93+
datafeed_api.list_datafeed.assert_called_with(
94+
session_token="session_token",
95+
key_manager_token="km_token"
96+
)
97+
datafeed_api.create_datafeed.assert_called_with(
98+
session_token="session_token",
99+
key_manager_token="km_token"
100+
)
101+
datafeed_api.read_datafeed.assert_called_with(
102+
session_token="session_token",
103+
key_manager_token="km_token",
104+
datafeed_id="test_id",
105+
ack_id=AckId(ack_id="")
106+
)
107+
108+
assert datafeed_loop._datafeed_id == "test_id"
109+
assert datafeed_loop._ack_id == "ack_id"
110+
111+
112+
@pytest.mark.asyncio
113+
async def test_start_datafeed_exist(datafeed_loop, datafeed_api, message_sent_event):
114+
datafeed_api.list_datafeed.return_value = [Datafeed(id="test_id_exist")]
115+
datafeed_api.read_datafeed.return_value = message_sent_event
116+
117+
await datafeed_loop.start()
118+
119+
datafeed_api.list_datafeed.assert_called_with(
120+
session_token="session_token",
121+
key_manager_token="km_token"
122+
)
123+
datafeed_api.read_datafeed.assert_called_with(
124+
session_token="session_token",
125+
key_manager_token="km_token",
126+
datafeed_id="test_id_exist",
127+
ack_id=AckId(ack_id="")
128+
)
129+
130+
assert datafeed_loop._datafeed_id == "test_id_exist"
131+
assert datafeed_loop._ack_id == "ack_id"
132+
133+
134+
@pytest.mark.asyncio
135+
async def test_start_datafeed_stale_datafeed(datafeed_loop, datafeed_api, message_sent_event):
136+
datafeed_api.list_datafeed.return_value = [Datafeed(id="fault_datafeed_id")]
137+
datafeed_api.create_datafeed.return_value = Datafeed(id="test_id")
138+
datafeed_api.read_datafeed.side_effect = [ApiException(400), message_sent_event]
139+
140+
await datafeed_loop.start()
141+
142+
datafeed_api.list_datafeed.assert_called_with(
143+
session_token="session_token",
144+
key_manager_token="km_token"
145+
)
146+
147+
datafeed_api.delete_datafeed.assert_called_with(
148+
session_token="session_token",
149+
key_manager_token="km_token",
150+
datafeed_id="fault_datafeed_id"
151+
)
152+
153+
datafeed_api.create_datafeed.assert_called_with(
154+
session_token="session_token",
155+
key_manager_token="km_token"
156+
)
157+
158+
datafeed_api.read_datafeed.assert_has_calls([
159+
call(
160+
session_token="session_token",
161+
key_manager_token="km_token",
162+
datafeed_id="fault_datafeed_id",
163+
ack_id=AckId(ack_id="")
164+
),
165+
call(
166+
session_token="session_token",
167+
key_manager_token="km_token",
168+
datafeed_id="test_id",
169+
ack_id=AckId(ack_id="")
170+
)
171+
])
172+
173+
assert datafeed_loop._datafeed_id == "test_id"
174+
assert datafeed_loop._ack_id == "ack_id"

tests/core/service_factory_test.py

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
from unittest.mock import MagicMock
2+
3+
import pytest
4+
5+
from symphony.bdk.core.auth.auth_session import AuthSession
6+
from symphony.bdk.core.client.api_client_factory import ApiClientFactory
7+
from symphony.bdk.core.config.loader import BdkConfigLoader
8+
from symphony.bdk.core.service.connection.connection_service import ConnectionService
9+
from symphony.bdk.core.service.datafeed.datafeed_loop_v1 import DatafeedLoopV1
10+
from symphony.bdk.core.service.datafeed.datafeed_loop_v2 import DatafeedLoopV2
11+
from symphony.bdk.core.service.message.message_service import MessageService
12+
from symphony.bdk.core.service.stream.stream_service import StreamService
13+
from symphony.bdk.core.service.user.user_service import UserService
14+
from symphony.bdk.core.service_factory import ServiceFactory
15+
from symphony.bdk.gen import ApiClient
16+
from tests.utils.resource_utils import get_config_resource_filepath
17+
18+
19+
@pytest.fixture()
20+
def api_client_factory():
21+
factory = MagicMock(ApiClientFactory)
22+
api_client = MagicMock(ApiClient)
23+
factory.get_pod_client.return_value = api_client
24+
factory.get_agent_client.return_value = api_client
25+
return factory
26+
27+
28+
@pytest.fixture()
29+
def config():
30+
config = BdkConfigLoader.load_from_file(get_config_resource_filepath("config.yaml"))
31+
return config
32+
33+
34+
@pytest.fixture()
35+
def service_factory(api_client_factory, config):
36+
factory = ServiceFactory(api_client_factory, AuthSession(None), config)
37+
return factory
38+
39+
40+
def test_get_user_service(service_factory):
41+
user_service = service_factory.get_user_service()
42+
assert user_service is not None
43+
assert type(user_service) == UserService
44+
45+
46+
def test_get_message_service(service_factory):
47+
message_service = service_factory.get_message_service()
48+
assert message_service is not None
49+
assert type(message_service) == MessageService
50+
51+
52+
def test_get_connection_service(service_factory):
53+
connection_service = service_factory.get_connection_service()
54+
assert connection_service is not None
55+
assert type(connection_service) == ConnectionService
56+
57+
58+
def test_get_stream_service(service_factory):
59+
stream_service = service_factory.get_stream_service()
60+
assert stream_service is not None
61+
assert type(stream_service) == StreamService
62+
63+
64+
def test_get_datafeed_loop(config, service_factory):
65+
datafeed_loop = service_factory.get_datafeed_loop()
66+
assert datafeed_loop is not None
67+
assert type(datafeed_loop) == DatafeedLoopV1
68+
69+
config.datafeed.version = "v1"
70+
datafeed_loop = service_factory.get_datafeed_loop()
71+
assert datafeed_loop is not None
72+
assert type(datafeed_loop) == DatafeedLoopV1
73+
74+
config.datafeed.version = "something"
75+
datafeed_loop = service_factory.get_datafeed_loop()
76+
assert datafeed_loop is not None
77+
assert type(datafeed_loop) == DatafeedLoopV1
78+
79+
config.datafeed.version = "v2"
80+
datafeed_loop = service_factory.get_datafeed_loop()
81+
assert datafeed_loop is not None
82+
assert type(datafeed_loop) == DatafeedLoopV2

0 commit comments

Comments
 (0)