blob: fa980cda93ffe5192f092fea6312f2c4f0bfc968 [file] [log] [blame]
Andy Bavier614af142020-08-07 14:49:56 -07001#!/usr/bin/env python
2
3# Copyright 2020-present Open Networking Foundation
4#
Hyunsun Moon200eba52021-04-05 21:31:54 -07005# SPDX-License-Identifier: LicenseRef-ONF-Member-Only-1.0
Andy Bavier614af142020-08-07 14:49:56 -07006
7import unittest
8import edge_monitoring_server as ems
9import datetime
10import pytz
Hyunsun Moon5f237ec2020-09-29 14:45:52 -070011import json
12import time
13
14
15test_edge = {
Andy Bavier8a5c9872020-10-21 13:17:53 -070016 'name': 'ace-menlo-pixel',
Hyunsun Moon5f237ec2020-09-29 14:45:52 -070017 'status': {
18 'control_plane': 'connected',
19 'user_plane': 'connected'
20 },
Jeremy Ronquillof4200252021-02-13 16:11:04 -080021 'speedtest': {
22 'ping': {
23 'dns': {
24 'min': 2.0,
25 'avg': 4.0,
26 'max': 6.0,
27 'stddev': 1.0
28 }
29 }
30 },
Hyunsun Moon200eba52021-04-05 21:31:54 -070031 'signal_quality': {
32 'rsrq': 30,
33 'rsrp': 80
34 },
35 'last_update': time.time()
36}
37
38test_edge_status_only = {
39 'name': 'ace-menlo-pixel',
40 'status': {
41 'control_plane': 'connected',
42 'user_plane': 'connected'
43 },
Jeremy Ronquillof4200252021-02-13 16:11:04 -080044 'last_update': time.time()
45}
46
47test_edge_no_speedtest = {
48 'name': 'ace-menlo-pixel',
49 'status': {
50 'control_plane': 'connected',
51 'user_plane': 'connected'
52 },
Hyunsun Moon200eba52021-04-05 21:31:54 -070053 'signal_quality': {
54 'rsrq': 30,
55 'rsrp': 80
56 },
57 'last_update': time.time()
58}
59
60test_edge_no_signal_quality = {
61 'name': 'ace-menlo-pixel',
62 'status': {
63 'control_plane': 'connected',
64 'user_plane': 'connected'
65 },
66 'speedtest': {
67 'ping': {
68 'dns': {
69 'min': 2.0,
70 'avg': 4.0,
71 'max': 6.0,
72 'stddev': 1.0
73 }
74 }
75 },
Hyunsun Moon5f237ec2020-09-29 14:45:52 -070076 'last_update': time.time()
77}
Andy Bavier614af142020-08-07 14:49:56 -070078
79
80class MyEvent:
Andy Bavierc41cf0c2020-09-02 14:49:21 -070081 def __init__ (self, location = "", description = "", summary = "", start = None, end = None, all_day = False):
Andy Bavier614af142020-08-07 14:49:56 -070082 self.location = location
83 self.description = description
84 self.summary = summary
85 self.start = start
86 self.end = end
Andy Bavierc41cf0c2020-09-02 14:49:21 -070087 self.all_day = all_day
Andy Bavier614af142020-08-07 14:49:56 -070088
89class MyEventNoLoc:
90 def __init__ (self, description = "", summary = ""):
91 self.description = description
92 self.summary = summary
93
94
95class TestEdgeMonitoringServer(unittest.TestCase):
Hyunsun Moon5f237ec2020-09-29 14:45:52 -070096 def setUp(self):
97 self.app = ems.app.test_client()
Hyunsun Moon200eba52021-04-05 21:31:54 -070098 self.emulated_time = time.mktime(time.strptime("2021-04-05 00:00:00", "%Y-%m-%d %H:%M:%S"))
99 self.time_method = time.time
100 time.time = self._get_time
101
102 def tearDown(self):
103 time.time = self.time_method
104
105 def _get_time(self):
106 return self.emulated_time
107
108 def _assert_status_metrics_exist(self, data):
109 self.assertTrue('aetheredge_status_control_plane{name="ace-menlo-pixel"} 2.0' in data)
110 self.assertTrue('aetheredge_status_user_plane{name="ace-menlo-pixel"} 2.0' in data)
111 self.assertTrue('aetheredge_last_update{name="ace-menlo-pixel"}' in data)
112 self.assertTrue('aetheredge_connect_test_ok{name="ace-menlo-pixel"} 1.0' in data)
113 self.assertTrue('aetheredge_ping_test_ok{name="ace-menlo-pixel"} 1.0' in data)
114 self.assertTrue('aetheredge_e2e_tests_ok{name="ace-menlo-pixel"} 1.0' in data)
115 self.assertTrue('aetheredge_e2e_tests_down{name="ace-menlo-pixel"} 0.0' in data)
116
117 def _assert_speedtest_metrics_exist(self, data):
118 self.assertTrue('aetheredge_ping_dns_test_min{name="ace-menlo-pixel"} 2.0' in data)
119 self.assertTrue('aetheredge_ping_dns_test_avg{name="ace-menlo-pixel"} 4.0' in data)
120 self.assertTrue('aetheredge_ping_dns_test_max{name="ace-menlo-pixel"} 6.0' in data)
121 self.assertTrue('aetheredge_ping_dns_test_stddev{name="ace-menlo-pixel"} 1.0' in data)
122
123 def _assert_signal_quality_metrics_exist(self, data):
124 self.assertTrue('aetheredge_signal_quality_rsrq{name="ace-menlo-pixel"} 30' in data)
125 self.assertTrue('aetheredge_signal_quality_rsrp{name="ace-menlo-pixel"} 80' in data)
Hyunsun Moon5f237ec2020-09-29 14:45:52 -0700126
Andy Bavier614af142020-08-07 14:49:56 -0700127 def test_match_location(self):
Andy Bavier8a5c9872020-10-21 13:17:53 -0700128 event = MyEvent(location = "ace-menlo-pixel-production")
129 self.assertTrue(ems.is_my_event(event, "ace-menlo-pixel"))
130 event = MyEvent(location = "(Compute)-MP-1-Aether Production")
131 self.assertTrue(ems.is_my_event(event, "ace-menlo-pixel"))
Andy Bavier614af142020-08-07 14:49:56 -0700132
133 def test_match_description(self):
Andy Bavier8a5c9872020-10-21 13:17:53 -0700134 event = MyEvent(description = "ace-menlo-pixel-production")
135 self.assertTrue(ems.is_my_event(event, "ace-menlo-pixel"))
136 event = MyEvent(description = "(Compute)-MP-1-Aether Production")
137 self.assertTrue(ems.is_my_event(event, "ace-menlo-pixel"))
Andy Bavier614af142020-08-07 14:49:56 -0700138
139 def test_match_summary(self):
Andy Bavier8a5c9872020-10-21 13:17:53 -0700140 event = MyEvent(summary = "ace-menlo-pixel-production")
141 self.assertTrue(ems.is_my_event(event, "ace-menlo-pixel"))
142 event = MyEvent(summary = "(Compute)-MP-1-Aether Production")
143 self.assertTrue(ems.is_my_event(event, "ace-menlo-pixel"))
Andy Bavier614af142020-08-07 14:49:56 -0700144
145 def test_no_match(self):
Andy Bavier8a5c9872020-10-21 13:17:53 -0700146 event = MyEvent(summary = "ace-menlo-pixel-production, (Compute)-MP-1-Aether Production")
147 self.assertFalse(ems.is_my_event(event, "ace-intel"))
Andy Bavier614af142020-08-07 14:49:56 -0700148 self.assertFalse(ems.is_my_event(event, "(Compute)-MP-1-Aether Staging"))
Andy Bavier8a5c9872020-10-21 13:17:53 -0700149 self.assertFalse(ems.is_my_event(event, "ace-menlo"))
Andy Bavier614af142020-08-07 14:49:56 -0700150
151 def test_missing_field(self):
Andy Bavier8a5c9872020-10-21 13:17:53 -0700152 event = MyEventNoLoc(description = "(Compute)-MP-1-Aether Production")
153 self.assertTrue(ems.is_my_event(event, "ace-menlo-pixel"))
Andy Bavier614af142020-08-07 14:49:56 -0700154
155 def test_in_window(self):
156 events = []
157 now = datetime.datetime.now(pytz.utc)
158 events.append(MyEvent(location = "(Compute)-MP-1-Aether Production",
159 start = now - datetime.timedelta(hours=1),
160 end = now + datetime.timedelta(hours=1)))
Andy Bavier8a5c9872020-10-21 13:17:53 -0700161 self.assertTrue(ems.in_maintenance_window(events, "ace-menlo-pixel", now))
162 self.assertFalse(ems.in_maintenance_window(events, "ace-tucson", now))
Andy Bavier614af142020-08-07 14:49:56 -0700163
164 def test_not_in_window(self):
165 events = []
166 now = datetime.datetime.now(pytz.utc)
Andy Bavier8a5c9872020-10-21 13:17:53 -0700167 events.append(MyEvent(location = "ace-menlo-pixel-production",
Andy Bavier614af142020-08-07 14:49:56 -0700168 start = now + datetime.timedelta(hours=1),
169 end = now + datetime.timedelta(hours=2)))
Andy Bavier8a5c9872020-10-21 13:17:53 -0700170 self.assertFalse(ems.in_maintenance_window(events, "ace-menlo-pixel", now))
Andy Bavier614af142020-08-07 14:49:56 -0700171
172 def test_no_events(self):
173 events = []
174 now = datetime.datetime.now(pytz.utc)
Andy Bavier8a5c9872020-10-21 13:17:53 -0700175 self.assertFalse(ems.in_maintenance_window(events, "ace-menlo-pixel", now))
Andy Bavier614af142020-08-07 14:49:56 -0700176
Andy Bavierc41cf0c2020-09-02 14:49:21 -0700177 def test_all_day_events(self):
178 events = []
Andy Bavier8a5c9872020-10-21 13:17:53 -0700179 events.append(MyEvent(location = "ace-menlo-pixel-production",
Andy Bavierc41cf0c2020-09-02 14:49:21 -0700180 start = datetime.datetime(2020, 9, 2, 0, 0),
181 end = datetime.datetime(2020, 9, 3, 0, 0),
182 all_day = True))
183
184 ems.process_all_day_events(events)
185
186 now = datetime.datetime(2020, 9, 2, 12, 0, tzinfo=pytz.utc)
Andy Bavier8a5c9872020-10-21 13:17:53 -0700187 self.assertTrue(ems.in_maintenance_window(events, "ace-menlo-pixel", now))
Andy Bavierc41cf0c2020-09-02 14:49:21 -0700188
189 now = datetime.datetime(2020, 9, 3, 12, 0, tzinfo=pytz.utc)
Andy Bavier8a5c9872020-10-21 13:17:53 -0700190 self.assertFalse(ems.in_maintenance_window(events, "ace-menlo-pixel", now))
Andy Bavierc41cf0c2020-09-02 14:49:21 -0700191
Hyunsun Moon5f237ec2020-09-29 14:45:52 -0700192 def test_get_edges(self):
193 response = self.app.get('/edges')
194 data = json.loads(response.get_data(as_text=True))
195 self.assertEqual(len(data['edges']), 1)
Andy Bavier8a5c9872020-10-21 13:17:53 -0700196 self.assertEqual(data['edges'][0]['name'], 'ace-example')
Hyunsun Moon5f237ec2020-09-29 14:45:52 -0700197
Andy Bavierf872e9a2021-03-22 12:06:25 -0700198 def test_create_and_delete_edge_legacy(self):
Hyunsun Moon5f237ec2020-09-29 14:45:52 -0700199 response = self.app.post('/edges', json=test_edge)
200 data = json.loads(response.get_data(as_text=True))
Andy Bavier8a5c9872020-10-21 13:17:53 -0700201 self.assertEqual(data['edge']['name'], 'ace-menlo-pixel')
Hyunsun Moon5f237ec2020-09-29 14:45:52 -0700202
203 response = self.app.get('/edges')
204 data = json.loads(response.get_data(as_text=True))
205 self.assertEqual(len(data['edges']), 2)
206
Andy Baviere47157d2020-12-11 14:13:12 -0700207 response = self.app.get('/edges/metrics')
208 data = response.get_data(as_text=True)
Andy Bavier5b4e28f2021-03-09 15:48:20 -0700209 print(data)
Hyunsun Moon200eba52021-04-05 21:31:54 -0700210
211 self._assert_status_metrics_exist(data)
212 self._assert_speedtest_metrics_exist(data)
213 self._assert_signal_quality_metrics_exist(data)
Andy Baviere47157d2020-12-11 14:13:12 -0700214
Andy Bavier8a5c9872020-10-21 13:17:53 -0700215 response = self.app.delete('/edges/ace-menlo-pixel')
Hyunsun Moon5f237ec2020-09-29 14:45:52 -0700216 data = json.loads(response.get_data(as_text=True))
217 self.assertEqual(data['result'], True)
Andy Baviere47157d2020-12-11 14:13:12 -0700218
219 response = self.app.get('/edges/metrics')
220 data = response.get_data(as_text=True)
Andy Bavier5b4e28f2021-03-09 15:48:20 -0700221 print(data)
222 self.assertFalse('ace-menlo-pixel' in data)
Hyunsun Moon5f237ec2020-09-29 14:45:52 -0700223
224 response = self.app.get('/edges')
225 data = json.loads(response.get_data(as_text=True))
226 self.assertEqual(len(data['edges']), 1)
Andy Bavierc41cf0c2020-09-02 14:49:21 -0700227
Andy Bavierf872e9a2021-03-22 12:06:25 -0700228 def test_create_and_delete_edge(self):
229 response = self.app.post('/testresults', json=test_edge)
230 data = json.loads(response.get_data(as_text=True))
231 self.assertEqual(data['edge']['name'], 'ace-menlo-pixel')
232
233 response = self.app.get('/edges')
234 data = json.loads(response.get_data(as_text=True))
235 self.assertEqual(len(data['edges']), 2)
236
237 response = self.app.get('/edges/metrics')
238 data = response.get_data(as_text=True)
239 print(data)
Hyunsun Moon200eba52021-04-05 21:31:54 -0700240
241 self._assert_status_metrics_exist(data)
242 self._assert_speedtest_metrics_exist(data)
243 self._assert_signal_quality_metrics_exist(data)
Andy Bavierf872e9a2021-03-22 12:06:25 -0700244
245 response = self.app.delete('/testresults/ace-menlo-pixel')
246 data = json.loads(response.get_data(as_text=True))
247 self.assertEqual(data['result'], True)
248
249 response = self.app.get('/edges/metrics')
250 data = response.get_data(as_text=True)
251 print(data)
252 self.assertFalse('ace-menlo-pixel' in data)
253
254 response = self.app.get('/edges')
255 data = json.loads(response.get_data(as_text=True))
256 self.assertEqual(len(data['edges']), 1)
Andy Bavier614af142020-08-07 14:49:56 -0700257
Jeremy Ronquillof4200252021-02-13 16:11:04 -0800258 def test_create_and_delete_edge_speed_test(self):
259 response = self.app.post('/testresults', json=test_edge)
260 data = json.loads(response.get_data(as_text=True))
261 self.assertEqual(data['edge']['name'], 'ace-menlo-pixel')
262
263 response = self.app.get('/edges/metrics')
264 data = response.get_data(as_text=True)
265 print(data)
266
Hyunsun Moon200eba52021-04-05 21:31:54 -0700267 self._assert_speedtest_metrics_exist(data)
268
269 response = self.app.delete('/testresults/ace-menlo-pixel')
270 data = json.loads(response.get_data(as_text=True))
271 self.assertEqual(data['result'], True)
272
273 def test_backwards_compatible_status_only(self):
274 response = self.app.post('/testresults', json=test_edge_status_only)
275 data = json.loads(response.get_data(as_text=True))
276 self.assertEqual(data['edge']['name'], 'ace-menlo-pixel')
277
278 response = self.app.get('/edges/metrics')
279 data = response.get_data(as_text=True)
280 print(data)
281
282 self.assertFalse('aetheredge_signal_quality_rsrq{name="ace-menlo-pixel"}' in data)
283 self.assertFalse('aetheredge_signal_quality_rsrp{name="ace-menlo-pixel"}' in data)
284
285 self._assert_status_metrics_exist(data)
Jeremy Ronquillof4200252021-02-13 16:11:04 -0800286
287 response = self.app.delete('/testresults/ace-menlo-pixel')
288 data = json.loads(response.get_data(as_text=True))
289 self.assertEqual(data['result'], True)
290
291 def test_backwards_compatible_no_speedtest(self):
292 response = self.app.post('/testresults', json=test_edge_no_speedtest)
293 data = json.loads(response.get_data(as_text=True))
294 self.assertEqual(data['edge']['name'], 'ace-menlo-pixel')
295
296 response = self.app.get('/edges/metrics')
297 data = response.get_data(as_text=True)
298 print(data)
299
300 self.assertFalse('aetheredge_ping_dns_test_min{name="ace-menlo-pixel"}' in data)
301 self.assertFalse('aetheredge_ping_dns_test_avg{name="ace-menlo-pixel"}' in data)
302 self.assertFalse('aetheredge_ping_dns_test_max{name="ace-menlo-pixel"}' in data)
303 self.assertFalse('aetheredge_ping_dns_test_stddev{name="ace-menlo-pixel"}' in data)
304
Hyunsun Moon200eba52021-04-05 21:31:54 -0700305 self._assert_status_metrics_exist(data)
306 self._assert_signal_quality_metrics_exist(data)
Jeremy Ronquillof4200252021-02-13 16:11:04 -0800307
308 response = self.app.delete('/testresults/ace-menlo-pixel')
309 data = json.loads(response.get_data(as_text=True))
310 self.assertEqual(data['result'], True)
311
Hyunsun Moon200eba52021-04-05 21:31:54 -0700312 def test_backwards_compatible_no_signal_quality(self):
313 response = self.app.post('/testresults', json=test_edge_no_signal_quality)
314 data = json.loads(response.get_data(as_text=True))
315 self.assertEqual(data['edge']['name'], 'ace-menlo-pixel')
316
317 response = self.app.get('/edges/metrics')
318 data = response.get_data(as_text=True)
319 print(data)
320
321 self.assertFalse('aetheredge_signal_quality_rsrq{name="ace-menlo-pixel"}' in data)
322 self.assertFalse('aetheredge_signal_quality_rsrp{name="ace-menlo-pixel"}' in data)
323
324 self._assert_status_metrics_exist(data)
325 self._assert_speedtest_metrics_exist(data)
326
327 response = self.app.delete('/testresults/ace-menlo-pixel')
328 data = json.loads(response.get_data(as_text=True))
329 self.assertEqual(data['result'], True)
330
331 def test_timeout_stale_result(self):
332 response = self.app.post('/testresults', json=test_edge)
333 data = json.loads(response.get_data(as_text=True))
334 print(json.dumps(data, indent=2))
335
336 self.assertEqual(data['edge']['status']['control_plane'], 'connected')
337 self.assertEqual(data['edge']['status']['user_plane'], 'connected')
338 self.assertEqual(data['edge']['speedtest']['ping']['dns']['avg'], 4.0)
339 self.assertTrue('signal_quality' in data['edge'])
340
341 self.emulated_time += (ems.NO_RESULT_THRESHOLD + 1)
342
343 response = self.app.get('/edges/ace-menlo-pixel')
344 data = json.loads(response.get_data(as_text=True))
345 print(json.dumps(data, indent=2))
346
347 self.assertEqual(data['edge']['status']['control_plane'], 'no result')
348 self.assertEqual(data['edge']['status']['user_plane'], 'no result')
349 self.assertEqual(data['edge']['speedtest']['ping']['dns']['avg'], 0.0)
350 self.assertFalse('signal_quality' in data['edge'])
351
352
Andy Bavier614af142020-08-07 14:49:56 -0700353if __name__ == '__main__':
354 suite = unittest.TestLoader().loadTestsFromTestCase(TestEdgeMonitoringServer)
355 unittest.TextTestRunner(verbosity=2).run(suite)