blob: 9e917f6bb562565118e31e80740c4b3978ab5cdd [file] [log] [blame]
Chip Boling67b674a2019-02-08 11:42:18 -06001#
2# Copyright 2018 the original author or authors.
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15#
16from unittest import TestCase, main
17from nose.tools import assert_raises
18from nose.twistedtools import deferred
19from copy import deepcopy
20from mock.mock_adapter_agent import MockAdapterAgent, MockCore
21from mock.mock_onu_handler import MockOnuHandler
22from mock.mock_olt_handler import MockOltHandler
23from mock.mock_onu import MockOnu
24from pyvoltha.adapters.extensions.omci.openomci_agent import OpenOMCIAgent, OpenOmciAgentDefaults
25from pyvoltha.adapters.extensions.omci.omci_defs import *
26from pyvoltha.common.utils.asleep import asleep
27from pyvoltha.adapters.extensions.omci.database.mib_db_api import DEVICE_ID_KEY, CLASS_ID_KEY, CREATED_KEY, \
28 MODIFIED_KEY, MDS_KEY, LAST_SYNC_KEY, VERSION_KEY, DatabaseStateError
29from pyvoltha.adapters.extensions.omci.database.mib_db_dict import MibDbVolatileDict
30
31
32DEFAULT_OLT_DEVICE_ID = 'default_olt_mock'
33DEFAULT_ONU_DEVICE_ID = 'default_onu_mock'
34DEFAULT_PON_ID = 0
35DEFAULT_ONU_ID = 0
36DEFAULT_ONU_SN = 'TEST00000001'
37
38OP = EntityOperations
39RC = ReasonCodes
40
41
42def chunk(indexable, chunk_size):
43 for i in range(0, len(indexable), chunk_size):
44 yield indexable[i:i + chunk_size]
45
46
47def hex2raw(hex_string):
48 return ''.join(chr(int(byte, 16)) for byte in chunk(hex_string, 2))
49
50
51class TestOnuDeviceEntry(TestCase):
52 """
53 Test the ONU Device Entry methods
54 """
55 def setUp(self):
56 self.adapter_agent = MockAdapterAgent()
57
58 custom = deepcopy(OpenOmciAgentDefaults)
59 custom['mib-synchronizer']['database'] = MibDbVolatileDict
60
61 self.agent = OpenOMCIAgent(MockCore, support_classes=custom)
62 self.agent.start()
63
64 def tearDown(self):
65 if self.agent is not None:
66 self.agent.stop()
67
68 if self.adapter_agent is not None:
69 self.adapter_agent.tearDown()
70
71 def setup_mock_olt(self, device_id=DEFAULT_OLT_DEVICE_ID):
72 handler = MockOltHandler(self.adapter_agent, device_id)
73 self.adapter_agent.add_device(handler.device)
74 return handler
75
76 def setup_mock_onu(self, parent_id=DEFAULT_OLT_DEVICE_ID,
77 device_id=DEFAULT_ONU_DEVICE_ID,
78 pon_id=DEFAULT_PON_ID,
79 onu_id=DEFAULT_ONU_ID,
80 serial_no=DEFAULT_ONU_SN):
81 handler = MockOnuHandler(self.adapter_agent, parent_id, device_id, pon_id, onu_id)
82 handler.serial_number = serial_no
83 onu = MockOnu(serial_no, self.adapter_agent, handler.device_id) \
84 if serial_no is not None else None
85 handler.onu_mock = onu
86 return handler
87
88 def setup_one_of_each(self):
89 # Most tests will use at lease one or more OLT and ONU
90 self.olt_handler = self.setup_mock_olt()
91 self.onu_handler = self.setup_mock_onu(parent_id=self.olt_handler.device_id)
92 self.onu_device = self.onu_handler.onu_mock
93
94 self.adapter_agent.add_child_device(self.olt_handler.device,
95 self.onu_handler.device)
96
97 def test_add_remove_device(self):
98 self.setup_one_of_each()
99 self.assertEqual(len(self.agent.device_ids()), 0)
100
101 onu_device = self.agent.add_device(DEFAULT_ONU_DEVICE_ID,
102 self.adapter_agent)
103 self.assertIsNotNone(onu_device)
104 self.assertEqual(len(self.agent.device_ids()), 1)
105 self.assertEqual(self.agent.get_device(DEFAULT_ONU_DEVICE_ID), onu_device)
106
107 # No MIB if not started
108 assert_raises(KeyError, onu_device.query_mib)
109
110 self.agent.remove_device(DEFAULT_ONU_DEVICE_ID)
111 self.assertEqual(len(self.agent.device_ids()), 1)
112
113 def test_delete_device(self):
114 self.setup_one_of_each()
115 self.assertEqual(len(self.agent.device_ids()), 0)
116
117 onu_device = self.agent.add_device(DEFAULT_ONU_DEVICE_ID,
118 self.adapter_agent)
119 self.assertIsNotNone(onu_device)
120 self.assertEqual(len(self.agent.device_ids()), 1)
121 self.assertEqual(self.agent.get_device(DEFAULT_ONU_DEVICE_ID), onu_device)
122 # Can delete if it was not started
123 onu_device.delete()
124 self.assertEqual(len(self.agent.device_ids()), 0)
125
126 ##########################################
127 # Delete of ONU device okay if it is started
128 onu_device = self.agent.add_device(DEFAULT_ONU_DEVICE_ID,
129 self.adapter_agent)
130 self.assertIsNotNone(onu_device)
131 self.assertEqual(len(self.agent.device_ids()), 1)
132 self.assertEqual(self.agent.get_device(DEFAULT_ONU_DEVICE_ID), onu_device)
133
134 # Start it and then delete it
135 onu_device.start()
136 onu_device.delete()
137 self.assertEqual(len(self.agent.device_ids()), 0)
138
139 @deferred(timeout=5)
140 def test_mib_query_fails_if_dev_not_started(self):
141 self.setup_one_of_each()
142
143 onu_device = self.agent.add_device(DEFAULT_ONU_DEVICE_ID,
144 self.adapter_agent)
145 self.assertIsNotNone(onu_device)
146 self.assertEqual(len(self.agent.device_ids()), 1)
147 self.assertEqual(self.agent.get_device(DEFAULT_ONU_DEVICE_ID), onu_device)
148
149 def not_called(_reason):
150 assert False, 'Should never be called'
151
152 def check_status(_results):
153 # Device not yet started. Query should fail with KeyError since
154 # ONU is not in database yet
155 assert_raises(KeyError, onu_device.query_mib)
156
157 # Yield context so that MIB Database callLater runs. This is a waiting
158 # Async task from when the OpenOMCIAgent was started.
159 d = asleep(0.2)
160 d.addCallbacks(check_status, not_called)
161
162 return d
163
164 @deferred(timeout=5)
165 def test_mib_query_ok_if_dev_started(self):
166 self.setup_one_of_each()
167
168 onu_device = self.agent.add_device(DEFAULT_ONU_DEVICE_ID,
169 self.adapter_agent)
170 self.assertIsNotNone(onu_device)
171 self.assertEqual(len(self.agent.device_ids()), 1)
172 self.assertEqual(self.agent.get_device(DEFAULT_ONU_DEVICE_ID), onu_device)
173
174 def not_called(_reason):
175 onu_device.stop()
176 assert False, 'Should never be called'
177
178 def check_status(_results):
179 # Device started. Query will succeed but nothing should be populated
180 # but the most basic items
181
182 results = onu_device.query_mib()
183 self.assertTrue(isinstance(results, dict))
184 self.assertEqual(results.get(DEVICE_ID_KEY), DEFAULT_ONU_DEVICE_ID)
185
186 self.assertIsNotNone(results.get(VERSION_KEY))
187 self.assertIsNotNone(results.get(CREATED_KEY))
188 self.assertIsNone(results.get(MODIFIED_KEY)) # Created! but not yet modified
189
190 self.assertEqual(results.get(MDS_KEY), 0)
191 self.assertIsNone(results.get(LAST_SYNC_KEY))
192
193 self.assertIsNone(results.get(CLASS_ID_KEY))
194
195 # Stopping still allows a query. Note you just delete a device
196 # to clean up any associated databases
197 onu_device.stop()
198 results = onu_device.query_mib()
199 self.assertTrue(isinstance(results, dict))
200
201 # Yield context so that MIB Database callLater runs. This is a waiting
202 # Async task from when the OpenOMCIAgent was started. But also start the
203 # device so that it's queued async state machines can run as well
204 onu_device.start()
205 d = asleep(0.2)
206 d.addCallbacks(check_status, not_called)
207
208 return d
209
210 @deferred(timeout=5)
211 def test_delete_scrubs_mib(self):
212 self.setup_one_of_each()
213
214 onu_device = self.agent.add_device(DEFAULT_ONU_DEVICE_ID,
215 self.adapter_agent)
216 self.assertIsNotNone(onu_device)
217 self.assertEqual(len(self.agent.device_ids()), 1)
218 self.assertEqual(self.agent.get_device(DEFAULT_ONU_DEVICE_ID), onu_device)
219
220 def not_called(_reason):
221 onu_device.stop()
222 assert False, 'Should never be called'
223
224 def check_status(_results):
225 # Device started. Query will succeed but nothing should be populated
226 # but the most basic items
227
228 results = onu_device.query_mib()
229 self.assertTrue(isinstance(results, dict))
230 self.assertEqual(results.get(DEVICE_ID_KEY), DEFAULT_ONU_DEVICE_ID)
231
232 # Delete should wipe out any MIB data. Note that a delete of a started
233 # or stopped ONU device is allowed. In this case we are deleting a
234 # started ONU Device
235
236 onu_device.delete()
237 assert_raises(Exception, onu_device.query_mib)
238 # TODO: When capabilities are supported, make sure capabilities get cleared as well
239
240 # Yield context so that MIB Database callLater runs. This is a waiting
241 # Async task from when the OpenOMCIAgent was started. But also start the
242 # device so that it's queued async state machines can run as well
243 onu_device.start()
244 d = asleep(0.2)
245 d.addCallbacks(check_status, not_called)
246
247 return d
248
249 # TODO: Test pub/sub interface if possible
250 # TODO: Test custom/vendor-specific ME support
251 # TODO: Test override of various state machines or OMCI tasks if possible
252
253
254if __name__ == '__main__':
255 main()
256