Skip to content

Commit b41f349

Browse files
committedNov 26, 2024
Add unit tests for coriolisclient.v1.logging.py module
1 parent b2ad9dc commit b41f349

File tree

1 file changed

+282
-0
lines changed

1 file changed

+282
-0
lines changed
 
Lines changed: 282 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,282 @@
1+
# Copyright 2024 Cloudbase Solutions Srl
2+
# All Rights Reserved.
3+
4+
import copy
5+
import datetime
6+
import ddt
7+
import requests
8+
import tempfile
9+
from unittest import mock
10+
11+
from keystoneauth1.exceptions import http
12+
13+
from coriolisclient import exceptions
14+
from coriolisclient.tests import test_base
15+
from coriolisclient.v1 import logging
16+
17+
18+
@ddt.ddt
19+
class LoggingClientTestCase(
20+
test_base.CoriolisBaseTestCase):
21+
"""Test suite for the Coriolis v1 Logging Client."""
22+
23+
@mock.patch.object(logging.LoggingClient, '_get_endpoint_url')
24+
def setUp(self, mock_get_endpoint_url):
25+
mock_get_endpoint_url.return_value = mock.sentinel.ep_url
26+
mock_client = mock.Mock()
27+
mock_client.verify = True
28+
super(LoggingClientTestCase, self).setUp()
29+
self.logger = logging.LoggingClient(mock_client)
30+
self.datetime = copy.deepcopy(datetime.datetime)
31+
32+
@mock.patch.object(logging.LoggingClient, '_get_endpoint_url')
33+
def test__init__(self, mock_get_endpoint_url):
34+
mock_get_endpoint_url.side_effect = Exception
35+
36+
with self.assertLogs(logger=logging.LOG, level="WARNING"):
37+
logger = logging.LoggingClient(None)
38+
39+
self.assertEqual(
40+
None,
41+
logger._ep_url
42+
)
43+
44+
def test_get_endpoint_url(self):
45+
self.logger._cli.get_endpoint.return_value = "url/endpoint_url/"
46+
47+
result = self.logger._get_endpoint_url(mock.sentinel.name)
48+
49+
self.assertEqual(
50+
"url/endpoint_url",
51+
result
52+
)
53+
self.logger._cli.get_endpoint.assert_called_once_with(
54+
service_type=mock.sentinel.name)
55+
56+
def test_get_endpoint_url_not_found(self):
57+
self.logger._cli.get_endpoint.return_value = None
58+
59+
self.assertRaises(
60+
exceptions.LoggingEndpointNotFound,
61+
self.logger._get_endpoint_url,
62+
mock.sentinel.name
63+
)
64+
self.logger._cli.get_endpoint.assert_called_once_with(
65+
service_type=mock.sentinel.name)
66+
67+
def test_get_endpoint_url_http_unauthorized(self):
68+
self.logger._cli.get_endpoint.side_effect = http.Unauthorized
69+
70+
with self.assertLogs(logger=logging.LOG, level="ERROR"):
71+
self.assertRaises(
72+
exceptions.HTTPAuthError,
73+
self.logger._get_endpoint_url,
74+
mock.sentinel.name
75+
)
76+
self.logger._cli.get_endpoint.assert_called_once_with(
77+
service_type=mock.sentinel.name)
78+
79+
@ddt.data(
80+
{
81+
"query_args": {
82+
"arg1": None,
83+
"arg2": None
84+
},
85+
"is_websocket": True,
86+
"expected_result":
87+
"ws:///None/sentinel.resource"
88+
},
89+
{
90+
"query_args": {
91+
"arg1": None,
92+
"arg2": "mock_arg2"
93+
},
94+
"_ep_url": "https:///ep_url",
95+
"is_websocket": True,
96+
"expected_result":
97+
"wss:///ep_url/sentinel.resource?arg2=mock_arg2"
98+
},
99+
{
100+
"query_args": {
101+
"arg1": "mock_arg1",
102+
"arg2": "mock_arg2"
103+
},
104+
"_ep_url": "https:///ep_url",
105+
"is_websocket": False,
106+
"expected_result": "https:///ep_url/sentinel.resource"
107+
"?arg1=mock_arg1&arg2=mock_arg2"
108+
}
109+
)
110+
@mock.patch.object(logging.LoggingClient, '_get_endpoint_url')
111+
def test_construct_url(self, data, mock_get_endpoint_url):
112+
self.logger._ep_url = None
113+
mock_get_endpoint_url.return_value = data.get("_ep_url", None)
114+
115+
result = self.logger._construct_url(
116+
mock.sentinel.resource,
117+
data.get("query_args"),
118+
is_websocket=data.get("is_websocket", False),
119+
)
120+
121+
self.assertEqual(
122+
data.get("expected_result"),
123+
result
124+
)
125+
126+
@ddt.data(
127+
(None, None, False),
128+
("1", 1, False),
129+
("1234567890123456789", None, True),
130+
("abc", None, True),
131+
("", None, True),
132+
)
133+
@ddt.unpack
134+
def test_convert_period_to_timestamp(
135+
self,
136+
period,
137+
expected_result,
138+
raises
139+
):
140+
if raises is False:
141+
result = self.logger._convert_period_to_timestamp(period)
142+
self.assertEqual(
143+
expected_result,
144+
result
145+
)
146+
else:
147+
self.assertRaises(
148+
exceptions.CoriolisException,
149+
self.logger._convert_period_to_timestamp,
150+
period
151+
)
152+
153+
@mock.patch.object(datetime, 'datetime')
154+
def test_convert_period_to_timestamp_period(
155+
self,
156+
mock_datetime
157+
):
158+
mock_datetime.utcnow.return_value = self.datetime.fromtimestamp(100000)
159+
result = self.logger._convert_period_to_timestamp("1d")
160+
self.assertEqual(
161+
13600,
162+
result
163+
)
164+
165+
@mock.patch.object(requests, "get")
166+
@mock.patch.object(logging.LoggingClient, "_construct_url")
167+
@mock.patch.object(logging.LoggingClient, "_convert_period_to_timestamp")
168+
def test_download_logs(
169+
self,
170+
mock_convert_period_to_timestamp,
171+
mock_construct_url,
172+
mock_get
173+
):
174+
mock_r = mock.Mock()
175+
mock_r.iter_content.return_value = [b'test_chunk1', b'test_chunk2']
176+
mock_get.return_value.__enter__.return_value = mock_r
177+
with tempfile.NamedTemporaryFile() as fd:
178+
self.logger.download_logs(
179+
mock.sentinel.app,
180+
fd.name,
181+
start_time=mock.sentinel.start_time,
182+
end_time=mock.sentinel.end_time
183+
)
184+
185+
result = fd.read()
186+
self.assertEqual(
187+
result,
188+
b'test_chunk1test_chunk2'
189+
)
190+
mock_get.assert_called_once_with(
191+
mock_construct_url.return_value,
192+
headers=self.logger._auth_headers,
193+
stream=True,
194+
verify=True
195+
)
196+
mock_construct_url.assert_called_once_with(
197+
"logs/sentinel.app/",
198+
{
199+
"start_date": mock_convert_period_to_timestamp.return_value,
200+
"end_date": mock_convert_period_to_timestamp.return_value,
201+
}
202+
)
203+
204+
def test_download_logs_no_app(self):
205+
self.assertRaises(
206+
exceptions.CoriolisException,
207+
self.logger.download_logs,
208+
"",
209+
None
210+
)
211+
212+
@mock.patch.object(requests, "get")
213+
def test_list_logs(self, mock_get):
214+
mock_get.return_value.raise_for_status.return_value = None
215+
mock_get.return_value.json.return_value = {
216+
"logs": ["mock_log1", "mock_log2"]
217+
}
218+
219+
result = self.logger.list_logs()
220+
221+
self.assertEqual(
222+
['mock_log1', 'mock_log2'],
223+
result
224+
)
225+
226+
227+
class CoriolisLogDownloadManagerTestCase(
228+
test_base.CoriolisBaseTestCase):
229+
"""Test suite for the Coriolis v1 Coriolis Log Download Manager."""
230+
231+
def setUp(self):
232+
mock_client = mock.Mock()
233+
super(CoriolisLogDownloadManagerTestCase, self).setUp()
234+
self.logger = logging.CoriolisLogDownloadManager(mock_client)
235+
self.logger._coriolis_cli = mock.Mock()
236+
self.logger.resource_class = mock.Mock()
237+
238+
def test_list(self):
239+
self.logger._coriolis_cli.list_logs.return_value = [
240+
"mock_log1", "mock_log2"]
241+
242+
result = self.logger.list()
243+
244+
self.assertEqual(
245+
[self.logger.resource_class.return_value,
246+
self.logger.resource_class.return_value],
247+
result
248+
)
249+
self.logger.resource_class.assert_has_calls([
250+
mock.call(self.logger, "mock_log1", loaded=True),
251+
mock.call(self.logger, "mock_log2", loaded=True)
252+
])
253+
254+
def test_get(self):
255+
result = self.logger.get(
256+
mock.sentinel.app,
257+
mock.sentinel.to,
258+
start_time=mock.sentinel.start_time,
259+
end_time=mock.sentinel.end_time,
260+
)
261+
262+
self.assertEqual(
263+
self.logger._coriolis_cli.download_logs.return_value,
264+
result
265+
)
266+
self.logger._coriolis_cli.download_logs.assert_called_once_with(
267+
mock.sentinel.app,
268+
mock.sentinel.to,
269+
start_time=mock.sentinel.start_time,
270+
end_time=mock.sentinel.end_time,
271+
)
272+
273+
def test_stream(self):
274+
self.logger.stream(
275+
app_name=mock.sentinel.app_name,
276+
severity=mock.sentinel.severity,
277+
)
278+
279+
self.logger._coriolis_cli.stream_logs.assert_called_once_with(
280+
app_name=mock.sentinel.app_name,
281+
severity=mock.sentinel.severity,
282+
)

0 commit comments

Comments
 (0)