def test_wait_set_parameter_values_state( self, mock_get_obj_param, mock_get_param, ): """ Test SetParameter return values""" mock_get_param.return_value = {} mock_get_obj_param.return_value = {} test_message_0 = models.SetParameterValuesResponse() test_message_0.Status = 0 test_message_1 = models.SetParameterValuesResponse() test_message_1.Status = 1 # TC-1: return value is 0. No fault acs_state = WaitSetParameterValuesState( self._get_acs(), 'done', 'invasive', ) rc = acs_state.read_msg(test_message_0) self.assertEqual(type(rc), AcsReadMsgResult) # It raises exception if we return 1 self.assertRaises( Tr069Error, acs_state.read_msg, test_message_1, ) # It passes if we return 1 and pass the non zero flag acs_state = WaitSetParameterValuesState( self._get_acs(), 'done', 'invasive', status_non_zero_allowed=True, ) rc = acs_state.read_msg(test_message_1) self.assertEqual(type(rc), AcsReadMsgResult) rc = acs_state.read_msg(test_message_0) self.assertEqual(type(rc), AcsReadMsgResult)
def test_wait_empty_message_state( self, mock_param_to_check, ): test_message_1 = models.DummyInput() test_message_2 = models.SetParameterValuesResponse() mock_param_to_check.return_value = True # test 1: No missing_param_transition # ensure we go to done state even when there are # optional params to check acs_state = WaitEmptyMessageState( self._get_acs(), when_done='done', ) rc = acs_state.read_msg(test_message_1) self.assertEqual(type(rc), AcsReadMsgResult) self.assertEqual(rc.next_state, 'done') self.assertEqual(rc.msg_handled, True) # test 2: No unknown_param_transition # ensure we go to missing state when there are # optional params to check and missing state is specified acs_state = WaitEmptyMessageState( self._get_acs(), when_done='done', when_missing='missing', ) rc = acs_state.read_msg(test_message_1) self.assertEqual(type(rc), AcsReadMsgResult) self.assertEqual(rc.next_state, 'missing') self.assertEqual(rc.msg_handled, True) # test 3: Negative test case send a message that is not empty # ensure we return msg_handled is False acs_state = WaitEmptyMessageState( self._get_acs(), when_done='done', when_missing='missing', ) rc = acs_state.read_msg(test_message_2) self.assertEqual(type(rc), AcsReadMsgResult) self.assertEqual(rc.next_state, None) self.assertEqual(rc.msg_handled, False) # test 4: Test get_msg rc = acs_state.get_msg(test_message_1) self.assertEqual(type(rc), AcsMsgAndTransition) self.assertEqual(type(rc.msg), models.DummyInput) self.assertEqual(rc.next_state, None)
def test_reboot_after_invasive_changes(self) -> None: """ Test the scenario where: - eNodeB has already been powered for 10 minutes without configuration - Setting parameters which are 'invasive' on the eNodeB - Simulate the scenario up until reboot, and test that enodebd does not try to complete configuration after reboot, because it is waiting for REM process to finish running - This test does not wait the ten minutes to simulate REM process finishing on the Baicells eNodeB 'Invasive' parameters are those which require special behavior to apply the changes for the eNodeB. In the case of the Baicells eNodeB, properly applying changes to invasive parameters requires rebooting the device. """ acs_state_machine = \ EnodebAcsStateMachineBuilder\ .build_acs_state_machine(EnodebDeviceName.BAICELLS_OLD) # Send an Inform message, wait for an InformResponse inform_msg = \ Tr069MessageBuilder.get_inform('48BF74', 'BaiStation_V100R001C00B110SPC002', '120200002618AGP0003', ['2 PERIODIC']) resp = acs_state_machine.handle_tr069_message(inform_msg) self.assertTrue(isinstance(resp, models.InformResponse), 'Should respond with an InformResponse') # Send an empty http request to kick off the rest of provisioning req = models.DummyInput() resp = acs_state_machine.handle_tr069_message(req) # Expect a request for an optional parameter, five times self.assertTrue(isinstance(resp, models.GetParameterValues), 'State machine should be requesting param values') req = Tr069MessageBuilder.get_fault() resp = acs_state_machine.handle_tr069_message(req) self.assertTrue(isinstance(resp, models.GetParameterValues), 'State machine should be requesting param values') req = Tr069MessageBuilder.get_fault() resp = acs_state_machine.handle_tr069_message(req) self.assertTrue(isinstance(resp, models.GetParameterValues), 'State machine should be requesting param values') req = Tr069MessageBuilder.get_fault() resp = acs_state_machine.handle_tr069_message(req) self.assertTrue(isinstance(resp, models.GetParameterValues), 'State machine should be requesting param values') req = Tr069MessageBuilder.get_fault() resp = acs_state_machine.handle_tr069_message(req) self.assertTrue(isinstance(resp, models.GetParameterValues), 'State machine should be requesting param values') req = Tr069MessageBuilder.get_fault() resp = acs_state_machine.handle_tr069_message(req) # Expect a request for read-only params self.assertTrue(isinstance(resp, models.GetParameterValues), 'State machine should be requesting param values') req = Tr069MessageBuilder.get_read_only_param_values_response() # Send back some typical values # And then SM should request regular parameter values resp = acs_state_machine.handle_tr069_message(req) self.assertTrue(isinstance(resp, models.GetParameterValues), 'State machine should be requesting param values') # Send back typical values for the regular parameters req = Tr069MessageBuilder.get_regular_param_values_response() resp = acs_state_machine.handle_tr069_message(req) # SM will be requesting object parameter values self.assertTrue( isinstance(resp, models.GetParameterValues), 'State machine should be requesting object param vals') # Send back some typical values for object parameters req = Tr069MessageBuilder.get_object_param_values_response() resp = acs_state_machine.handle_tr069_message(req) # In this scenario, the ACS and thus state machine will not need # to delete or add objects to the eNB configuration. # SM should then just be attempting to set parameter values self.assertTrue(isinstance(resp, models.SetParameterValues), 'State machine should be setting param values') # Send back confirmation that the parameters were successfully set req = models.SetParameterValuesResponse() req.Status = 0 resp = acs_state_machine.handle_tr069_message(req) # Since invasive parameters have been set, then to apply the changes # to the Baicells eNodeB, we need to reboot the device self.assertTrue(isinstance(resp, models.Reboot)) req = Tr069MessageBuilder.get_reboot_response() resp = acs_state_machine.handle_tr069_message(req) # After the reboot has been received, enodebd should end the # provisioning session self.assertTrue( isinstance(resp, models.DummyInput), 'After sending command to reboot the Baicells eNodeB, ' 'enodeb should end the TR-069 session.') # At this point, sometime after the eNodeB reboots, we expect it to # send an Inform indicating reboot. Since it should be in REM process, # we hold off on finishing configuration, and end TR-069 sessions. req = \ Tr069MessageBuilder.get_inform('48BF74', 'BaiStation_V100R001C00B110SPC002', '120200002618AGP0003', ['1 BOOT', 'M Reboot']) resp = acs_state_machine.handle_tr069_message(req) self.assertTrue( isinstance(resp, models.DummyInput), 'After receiving a post-reboot Inform, enodebd ' 'should end TR-069 sessions for 10 minutes to wait ' 'for REM process to finish.') # Pretend that we have waited, and now we are in normal operation again acs_state_machine.transition('wait_inform_post_reboot') req = \ Tr069MessageBuilder.get_inform('48BF74', 'BaiStation_V100R001C00B110SPC002', '120200002618AGP0003', ['2 PERIODIC']) resp = acs_state_machine.handle_tr069_message(req) self.assertTrue( isinstance(resp, models.InformResponse), 'After receiving a post-reboot Inform, enodebd ' 'should end TR-069 sessions for 10 minutes to wait ' 'for REM process to finish.') req = models.DummyInput() resp = acs_state_machine.handle_tr069_message(req) self.assertTrue(isinstance(resp, models.GetParameterValues), 'enodebd should be requesting params') self.assertTrue( len(resp.ParameterNames.string) > 1, 'Should be requesting transient params.')
def test_provision_without_invasive_changes(self) -> None: """ Test the scenario where: - eNodeB has already been powered for 10 minutes without configuration - Setting parameters which are 'non-invasive' on the eNodeB 'Invasive' parameters are those which require special behavior to apply the changes for the eNodeB. """ acs_state_machine = \ EnodebAcsStateMachineBuilder \ .build_acs_state_machine(EnodebDeviceName.BAICELLS_OLD) # Send an Inform message, wait for an InformResponse inform_msg = \ Tr069MessageBuilder.get_inform('48BF74', 'BaiStation_V100R001C00B110SPC001', '120200002618AGP0003', ['2 PERIODIC']) resp = acs_state_machine.handle_tr069_message(inform_msg) self.assertTrue(isinstance(resp, models.InformResponse), 'Should respond with an InformResponse') # Send an empty http request to kick off the rest of provisioning req = models.DummyInput() resp = acs_state_machine.handle_tr069_message(req) # Expect a request for an optional parameter, five times self.assertTrue(isinstance(resp, models.GetParameterValues), 'State machine should be requesting param values') req = Tr069MessageBuilder.get_fault() resp = acs_state_machine.handle_tr069_message(req) self.assertTrue(isinstance(resp, models.GetParameterValues), 'State machine should be requesting param values') req = Tr069MessageBuilder.get_fault() resp = acs_state_machine.handle_tr069_message(req) self.assertTrue(isinstance(resp, models.GetParameterValues), 'State machine should be requesting param values') req = Tr069MessageBuilder.get_fault() resp = acs_state_machine.handle_tr069_message(req) self.assertTrue(isinstance(resp, models.GetParameterValues), 'State machine should be requesting param values') req = Tr069MessageBuilder.get_fault() resp = acs_state_machine.handle_tr069_message(req) self.assertTrue(isinstance(resp, models.GetParameterValues), 'State machine should be requesting param values') req = Tr069MessageBuilder.get_fault() resp = acs_state_machine.handle_tr069_message(req) # Expect a request for read-only params self.assertTrue(isinstance(resp, models.GetParameterValues), 'State machine should be requesting param values') req = Tr069MessageBuilder.get_read_only_param_values_response() # Send back some typical values # And then SM should request regular parameter values resp = acs_state_machine.handle_tr069_message(req) self.assertTrue(isinstance(resp, models.GetParameterValues), 'State machine should be requesting param values') # Send back typical values for the regular parameters req = Tr069MessageBuilder.\ get_regular_param_values_response(admin_state=False, earfcndl=39150) resp = acs_state_machine.handle_tr069_message(req) # SM will be requesting object parameter values self.assertTrue( isinstance(resp, models.GetParameterValues), 'State machine should be requesting object param vals') # Send back some typical values for object parameters req = Tr069MessageBuilder.get_object_param_values_response() resp = acs_state_machine.handle_tr069_message(req) # In this scenario, the ACS and thus state machine will not need # to delete or add objects to the eNB configuration. # SM should then just be attempting to set parameter values self.assertTrue(isinstance(resp, models.SetParameterValues), 'State machine should be setting param values') # Send back confirmation that the parameters were successfully set req = models.SetParameterValuesResponse() req.Status = 0 resp = acs_state_machine.handle_tr069_message(req) # Expect a request for read-only params self.assertTrue(isinstance(resp, models.GetParameterValues), 'State machine should be requesting param values') req = Tr069MessageBuilder.get_read_only_param_values_response() # Send back some typical values # And then SM should continue polling the read-only params resp = acs_state_machine.handle_tr069_message(req) self.assertTrue(isinstance(resp, models.DummyInput), 'State machine should be ending session') # If a different eNB is suddenly plugged in, or the same eNB sends a # new Inform, enodebd should be able to handle it. # Send an Inform message, wait for an InformResponse inform_msg = \ Tr069MessageBuilder.get_inform('48BF74', 'BaiStation_V100R001C00B110SPC002', '120200002618AGP0003', ['2 PERIODIC']) resp = acs_state_machine.handle_tr069_message(inform_msg) self.assertTrue(isinstance(resp, models.InformResponse), 'Should respond with an InformResponse') # Send an empty http request to kick off the rest of provisioning req = models.DummyInput() resp = acs_state_machine.handle_tr069_message(req) # Expect a request for an optional parameter, three times self.assertTrue(isinstance(resp, models.GetParameterValues), 'State machine should be requesting param values')
def test_provisioning(self) -> None: acs_state_machine = self._build_acs_state_machine() # Send an Inform message, wait for an InformResponse inform_msg = self._get_inform() resp = acs_state_machine.handle_tr069_message(inform_msg) self.assertTrue(isinstance(resp, models.InformResponse), 'Should respond with an InformResponse') # Send an empty http request to kick off the rest of provisioning req = models.DummyInput() resp = acs_state_machine.handle_tr069_message(req) # Expect a request for an optional parameter, three times self.assertTrue(isinstance(resp, models.GetParameterValues), 'State machine should be requesting param values') req = self._get_fault() resp = acs_state_machine.handle_tr069_message(req) self.assertTrue(isinstance(resp, models.GetParameterValues), 'State machine should be requesting param values') req = self._get_fault() resp = acs_state_machine.handle_tr069_message(req) self.assertTrue(isinstance(resp, models.GetParameterValues), 'State machine should be requesting param values') req = self._get_fault() resp = acs_state_machine.handle_tr069_message(req) # Expect a request for read-only params self.assertTrue(isinstance(resp, models.GetParameterValues), 'State machine should be requesting param values') req = self._get_read_only_param_values_response() # Send back some typical values # And then SM should request regular parameter values resp = acs_state_machine.handle_tr069_message(req) self.assertTrue(isinstance(resp, models.GetParameterValues), 'State machine should be requesting param values') # Send back typical values for the regular parameters req = self._get_regular_param_values_response() resp = acs_state_machine.handle_tr069_message(req) # SM will be requesting object parameter values self.assertTrue(isinstance(resp, models.GetParameterValues), 'State machine should be requesting object param vals') # Send back some typical values for object parameters req = self._get_object_param_values_response() resp = acs_state_machine.handle_tr069_message(req) # In this scenario, the ACS and thus state machine will not need # to delete or add objects to the eNB configuration. # SM should then just be attempting to set parameter values self.assertTrue(isinstance(resp, models.SetParameterValues), 'State machine should be setting param values') # Send back confirmation that the parameters were successfully set req = models.SetParameterValuesResponse() req.Status = 0 resp = acs_state_machine.handle_tr069_message(req) # SM should be attempting to reboot the Baicells device self.assertTrue(isinstance(resp, models.Reboot), 'State machine should be rebooting the eNB') req = self._get_reboot_response() resp = acs_state_machine.handle_tr069_message(req) # SM should be trying to end the session with a dummy message self.assertTrue(isinstance(resp, models.DummyInput)) req = self._get_reboot_inform() resp = acs_state_machine.handle_tr069_message(req) # SM should have responded to an Inform message with an Inform response self.assertTrue(isinstance(resp, models.InformResponse)) req = models.DummyInput() resp = acs_state_machine.handle_tr069_message(req) # And now the SM has finished provisioning, and should only request # the transient, read-only parameters self.assertTrue(isinstance(resp, models.GetParameterValues), 'State machine should be requesting read-only params') # The eNodeB will send an Inform after ~10 minutes anyways, even # during a provisioning session req = self._get_inform() resp = acs_state_machine.handle_tr069_message(req) self.assertTrue(isinstance(resp, models.InformResponse), 'State machine should handle unexpected Inform msgs') return
def test_provision(self, mock_get_state) -> None: """ Test the basic provisioning workflow 1 - enodeb sends Inform, enodebd sends InformResponse 2 - enodeb sends empty HTTP message, 3 - enodebd sends get transient params, updates the device state. 4 - enodebd sends get param values, updates the device state 5 - enodebd, sets fields including SAS fields. Args: mock_get_state (Any): mocking get_cbsd_state method """ mock_get_state.return_value = MOCK_CBSD_STATE logging.root.level = logging.DEBUG acs_state_machine = EnodebAcsStateMachineBuilder.build_acs_state_machine( EnodebDeviceName.FREEDOMFI_ONE) acs_state_machine._service.config = _get_service_config() acs_state_machine.desired_cfg = build_desired_config( acs_state_machine.mconfig, acs_state_machine.service_config, acs_state_machine.device_cfg, acs_state_machine.data_model, acs_state_machine.config_postprocessor, ) inform = Tr069MessageBuilder.get_inform( oui="000E8F", sw_version="TEST3920@210901", enb_serial="2006CW5000023", ) resp = acs_state_machine.handle_tr069_message(inform) self.assertTrue( isinstance(resp, models.InformResponse), 'Should respond with an InformResponse', ) # Send an empty http request req = models.DummyInput() resp = acs_state_machine.handle_tr069_message(req) # Expect a request for read-only params self.assertTrue( isinstance(resp, models.GetParameterValues), 'State machine should be requesting param values', ) for tr69nodes in StatusParameters.STATUS_PARAMETERS.values(): self.assertIn(tr69nodes.path, resp.ParameterNames.string) req = self._get_ff_one_read_only_param_values_resp() get_resp = acs_state_machine.handle_tr069_message(req) self.assertTrue( isinstance(get_resp, models.GetParameterValues), 'State machine should be requesting param values', ) req = self._get_freedomfi_one_param_values_response() resp = acs_state_machine.handle_tr069_message(req) self.assertTrue( isinstance(resp, models.SetParameterValues), 'State machine should be setting parameters', ) self.assertIsNotNone( resp.ParameterKey.Data, 'ParameterKey should be set for FreedomFiOne eNB', ) msg = models.SetParameterValuesResponse() msg.Status = 1 get_resp = acs_state_machine.handle_tr069_message(msg) self.assertTrue( isinstance(get_resp, models.GetParameterValues), 'We should read back all parameters', ) req = self._get_freedomfi_one_param_values_response() resp = acs_state_machine.handle_tr069_message(req) self.assertTrue( isinstance(resp, models.DummyInput), 'Provisioning completed with Dummy response', )
def test_provision(self) -> None: """ Test the basic provisioning workflow 1 - enodeb sends Inform, enodebd sends InformResponse 2 - enodeb sends empty HTTP message, 3 - enodebd sends get transient params, updates the device state. 4 - enodebd sends get param values, updates the device state 5 - enodebd, sets fields including SAS fields. """ logging.root.level = logging.DEBUG acs_state_machine = self.build_freedomfi_one_acs_state_machine() inform = Tr069MessageBuilder.get_inform( oui="000E8F", sw_version="TEST3920@210901", enb_serial="2006CW5000023", ) resp = acs_state_machine.handle_tr069_message(inform) self.assertTrue( isinstance(resp, models.InformResponse), 'Should respond with an InformResponse', ) # Send an empty http request req = models.DummyInput() resp = acs_state_machine.handle_tr069_message(req) # Expect a request for read-only params self.assertTrue( isinstance(resp, models.GetParameterValues), 'State machine should be requesting param values', ) for tr_69_nodes in StatusParameters.STATUS_PARAMETERS.values(): self.assertIn(tr_69_nodes.path, resp.ParameterNames.string) req = self._get_freedomfi_one_read_only_param_values_response() get_resp = acs_state_machine.handle_tr069_message(req) self.assertTrue( isinstance(get_resp, models.GetParameterValues), 'State machine should be requesting param values', ) req = self._get_freedomfi_one_param_values_response() resp = acs_state_machine.handle_tr069_message(req) self.assertTrue( isinstance(resp, models.SetParameterValues), 'State machine should be setting parameters', ) self.assertIsNotNone( resp.ParameterKey.Data, 'ParameterKey should be set for FreedomFiOne eNB', ) msg = models.SetParameterValuesResponse() msg.Status = 1 get_resp = acs_state_machine.handle_tr069_message(msg) self.assertTrue( isinstance(get_resp, models.GetParameterValues), 'We should read back all parameters', ) req = self._get_freedomfi_one_param_values_response() resp = acs_state_machine.handle_tr069_message(req) self.assertTrue( isinstance(resp, models.DummyInput), 'Provisioning completed with Dummy response', )
def test_provisioning(self) -> None: acs_state_machine = self._build_acs_state_machine() # Send an Inform message, wait for an InformResponse inform_msg = self._get_inform() resp = acs_state_machine.handle_tr069_message(inform_msg) self.assertTrue(isinstance(resp, models.InformResponse), 'Should respond with an InformResponse') # Send an empty http request to kick off the rest of provisioning req = models.DummyInput() resp = acs_state_machine.handle_tr069_message(req) # Expect a request for an optional parameter, three times self.assertTrue(isinstance(resp, models.GetParameterValues), 'State machine should be requesting param values') req = self._get_fault() resp = acs_state_machine.handle_tr069_message(req) self.assertTrue(isinstance(resp, models.GetParameterValues), 'State machine should be requesting param values') req = self._get_fault() resp = acs_state_machine.handle_tr069_message(req) self.assertTrue(isinstance(resp, models.GetParameterValues), 'State machine should be requesting param values') req = self._get_fault() resp = acs_state_machine.handle_tr069_message(req) # Expect a request for read-only params self.assertTrue(isinstance(resp, models.GetParameterValues), 'State machine should be requesting param values') req = self._get_read_only_param_values_response() # Send back some typical values # And then SM should request regular parameter values resp = acs_state_machine.handle_tr069_message(req) self.assertTrue(isinstance(resp, models.GetParameterValues), 'State machine should be requesting param values') # Send back typical values for the regular parameters req = self._get_regular_param_values_response() resp = acs_state_machine.handle_tr069_message(req) # SM will be requesting object parameter values self.assertTrue( isinstance(resp, models.GetParameterValues), 'State machine should be requesting object param vals') # Send back some typical values for object parameters req = self._get_object_param_values_response() resp = acs_state_machine.handle_tr069_message(req) # In this scenario, the ACS and thus state machine will not need # to delete or add objects to the eNB configuration. # SM should then just be attempting to set parameter values self.assertTrue(isinstance(resp, models.SetParameterValues), 'State machine should be setting param values') # Send back confirmation that the parameters were successfully set req = models.SetParameterValuesResponse() req.Status = 0 resp = acs_state_machine.handle_tr069_message(req) # Expect a request for read-only params self.assertTrue(isinstance(resp, models.GetParameterValues), 'State machine should be requesting param values') req = self._get_read_only_param_values_response() # Send back some typical values # And then SM should continue polling the read-only params resp = acs_state_machine.handle_tr069_message(req) self.assertTrue(isinstance(resp, models.GetParameterValues), 'State machine should be requesting param values') # Expect a request for read-only params self.assertTrue(isinstance(resp, models.GetParameterValues), 'State machine should be requesting param values') req = self._get_read_only_param_values_response() # Send back some typical values resp = acs_state_machine.handle_tr069_message(req) self.assertTrue(isinstance(resp, models.GetParameterValues), 'State machine should be requesting param values') # If a different eNB is suddenly plugged in, or the same eNB sends a # new Inform, enodebd should be able to handle it. # Send an Inform message, wait for an InformResponse inform_msg = self._get_inform() resp = acs_state_machine.handle_tr069_message(inform_msg) self.assertTrue(isinstance(resp, models.InformResponse), 'Should respond with an InformResponse') # Send an empty http request to kick off the rest of provisioning req = models.DummyInput() resp = acs_state_machine.handle_tr069_message(req) # Expect a request for an optional parameter, three times self.assertTrue(isinstance(resp, models.GetParameterValues), 'State machine should be requesting param values') return