blob: d0d572def900278212e2b37f6829988bb70a9868 [file] [log] [blame]
Holger Hans Peter Freyther799fe622018-11-07 03:48:58 +00001# osmo_ms_driver: Location Update Test
Holger Hans Peter Freyther574e62f2018-06-20 09:15:15 +01002# Create MS's and wait for the Location Update to succeed.
Holger Hans Peter Freyther30cc0212018-02-25 21:34:35 +00003#
4# Copyright (C) 2018 by Holger Hans Peter Freyther
5#
6# This program is free software: you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as
8# published by the Free Software Foundation, either version 3 of the
9# License, or (at your option) any later version.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with this program. If not, see <http://www.gnu.org/licenses/>.
18
Holger Hans Peter Freyther30cc0212018-02-25 21:34:35 +000019from datetime import timedelta
20
Holger Hans Peter Freyther75c9cc72019-04-30 15:38:51 +010021from .test_support import TestBase
22
Holger Hans Peter Freyther337141f2019-02-23 09:58:59 +000023import collections
Holger Hans Peter Freyther92cc0c92019-04-28 16:55:30 +010024import json
Holger Hans Peter Freyther30cc0212018-02-25 21:34:35 +000025import time
26
Holger Hans Peter Freyther61f28772019-04-27 14:25:22 +010027# Key used for the result dictionary
28LU_RESULT_NAME = 'lu_time'
Holger Hans Peter Freyther30cc0212018-02-25 21:34:35 +000029
Holger Hans Peter Freyther61f28772019-04-27 14:25:22 +010030def has_lu_time(result):
31 """
32 Returns true if a LU occurred.
33 """
34 return result.has_result(LU_RESULT_NAME)
Holger Hans Peter Freyther30cc0212018-02-25 21:34:35 +000035
Holger Hans Peter Freyther61f28772019-04-27 14:25:22 +010036def lu_time(result):
37 """
38 Returns the time of the LU occurrence.
39 """
40 return result.get_result(LU_RESULT_NAME, default=0)
Holger Hans Peter Freyther30cc0212018-02-25 21:34:35 +000041
Holger Hans Peter Freyther61f28772019-04-27 14:25:22 +010042def lu_delay(result):
43 """
44 Returns the delay from LU success to MS start time.
45 """
46 return lu_time(result) - result.start_time()
Holger Hans Peter Freyther0f6e4102018-06-23 15:52:25 +010047
Holger Hans Peter Freyther61f28772019-04-27 14:25:22 +010048def set_lu_time(result, time):
49 """
50 Sets/Overrides the time of the LU success for this MS.
51 """
52 result.set_result(LU_RESULT_NAME, time)
Holger Hans Peter Freyther30cc0212018-02-25 21:34:35 +000053
Holger Hans Peter Freyther337141f2019-02-23 09:58:59 +000054
55LUStats = collections.namedtuple("LUStats", ["num_attempted", "num_completed",
56 "min_latency", "max_latency"])
57
Holger Hans Peter Freyther75c9cc72019-04-30 15:38:51 +010058class MassUpdateLocationTest(TestBase):
Holger Hans Peter Freyther92cc0c92019-04-28 16:55:30 +010059 def __init__(self, name, event_server, results):
Holger Hans Peter Freyther75c9cc72019-04-30 15:38:51 +010060 super().__init__(name, event_server, results)
Holger Hans Peter Freyther92cc0c92019-04-28 16:55:30 +010061 self._event_server.register(self.handle_msg)
Holger Hans Peter Freyther92cc0c92019-04-28 16:55:30 +010062
Holger Hans Peter Freytherdbb16e82019-04-30 22:03:12 +010063 def configure(self, subscribers, mobiles):
64 # Enable the LU test script in each mobile
65 for mobile in mobiles:
66 mobile.set_cfg_item('run_lu_test', True)
67
68 self._num_subscribers = len(subscribers)
69 self._outstanding = self._num_subscribers
Holger Hans Peter Freyther92cc0c92019-04-28 16:55:30 +010070
71 def handle_msg(self, _data, addr, time):
72 data = json.loads(_data.decode())
73
74 if data['type'] == 'event':
75 if data['data']['lu_done'] == 1:
76 ms = self._results[data['ms']]
77 if not has_lu_time(ms):
78 self._outstanding = self._outstanding - 1
79 set_lu_time(ms, time)
80 self.log("MS performed LU ", ms=ms, at=time, lu_delay=lu_delay(ms))
81
Holger Hans Peter Freyther75c9cc72019-04-30 15:38:51 +010082 def has_completed(self):
Holger Hans Peter Freyther92cc0c92019-04-28 16:55:30 +010083 return self._outstanding == 0
84
85 def wait_for_test(self, loop, deadline):
86 """Waits up to the absolute deadline for the test to complete."""
Holger Hans Peter Freyther75c9cc72019-04-30 15:38:51 +010087 while not self.has_completed():
Holger Hans Peter Freyther92cc0c92019-04-28 16:55:30 +010088 now_time = time.clock_gettime(time.CLOCK_MONOTONIC)
89 sleep_time = deadline - now_time
90 if sleep_time < 0:
91 break
92 loop.schedule_timeout(sleep_time)
93 loop.select()
94
95 def find_min_max(self, results):
96 min_value = max_value = None
97 for result in results:
98 if min_value is None or lu_delay(result) < min_value:
99 min_value = lu_delay(result)
100 if max_value is None or lu_delay(result) > max_value:
101 max_value = lu_delay(result)
102 return min_value, max_value
103
104 def get_result_values(self):
105 """
106 Returns the raw result values of the test run in any order.
107 """
108 return self._results.values()
109
110 def get_stats(self):
111 """
112 Returns a statistical summary of the test.
113 """
114 attempted = self._num_subscribers
115 completed = attempted - self._outstanding
116 min_latency, max_latency = self.find_min_max(filter(lambda x: has_lu_time(x), self._results.values()))
117 return LUStats(attempted, completed, min_latency, max_latency)
118
119 def print_stats(self):
120 stats = self.get_stats()
121 all_completed = stats.num_attempted == stats.num_completed
122
123 self.log("Tests done", all_completed=all_completed,
124 min=stats.min_latency, max=stats.max_latency)
125
126 def lus_less_than(self, acceptable_delay):
127 """
128 Returns LUs that completed within the acceptable delay.
129 """
130 res = []
131 for result in self._results.values():
132 if not has_lu_time(result):
133 continue
134 if timedelta(seconds=lu_delay(result)) >= acceptable_delay:
135 continue
136 res.append(result)
137 return res
138