-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_protoconfloader.py
More file actions
171 lines (132 loc) · 4.89 KB
/
test_protoconfloader.py
File metadata and controls
171 lines (132 loc) · 4.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
import asyncio
import logging
from unittest.mock import AsyncMock, MagicMock, patch, Mock
import pytest
from watchdog.events import FileSystemEvent
from protoconfloader.protoconfloader import Configuration, _EventHandler
from tests.test_data.crawler_pb2 import CrawlerService
@pytest.mark.asyncio
async def test_load_config_local():
# Setup
mock_open = AsyncMock()
mock_open.return_value.__aenter__.return_value.read = AsyncMock(
return_value='{"crawlers": []}'
)
message = CrawlerService()
mock_logger = MagicMock()
config = Configuration(message, "test_service", mock_logger)
# Act
await config.load_config("tests/test_data", "config.json")
assert message.log_level == 3
await config.load_config("tests/test_data", "config.json")
mock_logger.info.assert_called_once_with("Config file is already loaded")
@pytest.mark.asyncio
async def test_load_invalid_json_config():
# Setup
mock_open = AsyncMock()
mock_open.return_value.__aenter__.return_value.read = AsyncMock(
return_value='{"crawlers": [}' # Invalid JSON
)
message = CrawlerService()
config = Configuration(message, "crawler/text_crawler", logging.getLogger())
# Act & Assert
with patch("builtins.open", mock_open):
with pytest.raises(RuntimeError, match="Error decoding JSON"):
await config.load_config("tests/test_data", "invalid_config.json")
@pytest.mark.asyncio
async def test_listen_to_changes_remote():
# Setup
mock_channel = AsyncMock()
mock_client = MagicMock()
mock_client.SubscribeForConfig = AsyncMock(
return_value=iter([MagicMock(value=MagicMock())])
)
mock_channel.return_value.__aenter__.return_value = mock_client
message = CrawlerService()
config = Configuration(message, "crawler/text_crawler", logging.getLogger())
mock_callback = AsyncMock()
callback_event = asyncio.Event()
# Act
await config.load_config("tests/test_data", "config.json")
async def async_callback(message):
await mock_callback(message)
callback_event.set()
config.on_config_change(async_callback)
watch_task = asyncio.create_task(config.watch_config())
await asyncio.sleep(0.3)
# Assert
assert callback_event.is_set()
mock_callback.assert_called_once()
watch_task.cancel()
await asyncio.gather(watch_task, return_exceptions=True)
@pytest.mark.asyncio
async def test_load_config_nonexistent_file():
# Setup
message = CrawlerService()
config = Configuration(message, "test_service", logging.getLogger())
mock_callback = AsyncMock()
callback_event = asyncio.Event()
# Act
async def async_callback(message):
await mock_callback(message)
callback_event.set()
config.on_config_change(async_callback)
# Act & Assert
with patch("builtins.open", side_effect=FileNotFoundError):
with pytest.raises(FileNotFoundError):
await config.load_config("tests/test_data", "nonexistent_config.json")
assert not callback_event.is_set()
mock_callback.assert_not_called()
@pytest.mark.asyncio
async def test_watch_config_remote_same_log_level():
# Setup
mock_channel = AsyncMock()
mock_client = MagicMock()
mock_client.SubscribeForConfig = AsyncMock(
return_value=iter([MagicMock(value=MagicMock(log_level=3))])
)
mock_channel.return_value.__aenter__.return_value = mock_client
message = CrawlerService()
config = Configuration(message, "crawler/text_crawler", logging.getLogger())
mock_callback = AsyncMock()
callback_event = asyncio.Event()
# Act
await config.load_config("tests/test_data", "config.json")
async def async_callback(message):
await mock_callback(message)
callback_event.set()
config.on_config_change(async_callback)
watch_task = asyncio.create_task(config.watch_config())
await asyncio.sleep(0.3)
# Assert
assert callback_event.is_set()
mock_callback.assert_called_once()
assert message.log_level == 17
watch_task.cancel()
await asyncio.gather(watch_task, return_exceptions=True)
def test_on_modified_nonexistent_file():
# Setup
event = FileSystemEvent("nonexistent_config.json")
mock_logger = MagicMock()
handler = _EventHandler(
cb=MagicMock(), config_file="nonexistent_config.json", logger=mock_logger
)
# Act
handler.on_modified(event)
# Assert
# handler.load_config_cb.assert_not_called()
mock_logger.error.assert_called_once_with(
"Error loading config: %s", "nonexistent_config.json"
)
def test_set_logger():
# Setup
config = Configuration(
message=Mock(), config_path="crawler/text_crawler", logger=logging.getLogger()
)
new_logger = logging.getLogger("new_logger")
# Act
config.set_logger(new_logger)
# Assert
assert config.logger == new_logger
if __name__ == "__main__":
pytest.main()