class BurstContollerTest(BaseControllersTest): """ Unit tests for burst_controller """ def setUp(self): """ Sets up the environment for testing; creates a `BurstController` """ BaseControllersTest.init(self) self.burst_c = BurstController() def tearDown(self): """ Cleans up the environment after testing is done """ self.cleanup() self.clean_database() def test_index(self): """ Test that index returns a dict with all required keys. Also check that the default portlets are populated, with only the first being the TimeSeries portlet and the rest are empty. """ result_dict = self.burst_c.index() self.assertTrue('burst_list' in result_dict and result_dict['burst_list'] == []) self.assertTrue('available_metrics' in result_dict and isinstance(result_dict['available_metrics'], list)) self.assertTrue('portletList' in result_dict and isinstance(result_dict['portletList'], list)) self.assertEqual(result_dict[common.KEY_SECTION], "burst") self.assertTrue('burstConfig' in result_dict and isinstance(result_dict['burstConfig'], BurstConfiguration)) portlets = json.loads(result_dict['selectedPortlets']) portlet_id = dao.get_portlet_by_identifier("TimeSeries").id for tab_idx, tab in enumerate(portlets): for index_in_tab, value in enumerate(tab): if tab_idx == 0 and index_in_tab == 0: self.assertEqual(value, [portlet_id, "TimeSeries"]) else: self.assertEqual(value, [-1, "None"]) self.assertTrue(result_dict['draw_hidden_ranges']) def test_load_burst_history(self): """ Create two burst, load the burst and check that we get back the same stored bursts. """ self._store_burst(self.test_project.id, 'started', {'test': 'test'}, 'burst1') burst = self._store_burst(self.test_project.id, 'started', {'test': 'test'}, 'burst2') cherrypy.session[common.KEY_BURST_CONFIG] = burst result_dict = self.burst_c.load_burst_history() burst_history = result_dict['burst_list'] self.assertEqual(len(burst_history), 2) for burst in burst_history: self.assertTrue(burst.name in ('burst1', 'burst2')) def test_get_selected_burst(self): """ Create burst, add it to session, then check that get_selected_burst return the same burst. Also check that for an unstored entity we get back 'None' """ burst_entity = BurstConfiguration(self.test_project.id, 'started', {}, 'burst1') cherrypy.session[common.KEY_BURST_CONFIG] = burst_entity stored_id = self.burst_c.get_selected_burst() self.assertEqual(stored_id, 'None') burst_entity = dao.store_entity(burst_entity) cherrypy.session[common.KEY_BURST_CONFIG] = burst_entity stored_id = self.burst_c.get_selected_burst() self.assertEqual(str(stored_id), str(burst_entity.id)) def test_get_portlet_configurable_interface(self): """ Look up that an AdapterConfiguration is returned for the default portlet configuration, if we look at index (0, 0) where TimeSeries portlet should be default. """ self.burst_c.index() result = self.burst_c.get_portlet_configurable_interface(0) self.assertTrue(common.KEY_PARAMETERS_CONFIG in result) self.assertFalse(result[common.KEY_PARAMETERS_CONFIG]) adapter_config = result['adapters_list'] # Default TimeSeries portlet should be available, so we expect # adapter_config to be a list of AdapterConfiguration with one element self.assertEqual(len(adapter_config), 1) self.assertTrue(isinstance(adapter_config[0], AdapterConfiguration)) def test_portlet_tab_display(self): """ Update the default portlet configuration, by storing a TimeSeries portlet for all postions. Then check that we get the same configuration. """ self.burst_c.index() portlet_id = dao.get_portlet_by_identifier("TimeSeries").id one_tab = [[portlet_id, "TimeSeries"] for _ in range(NUMBER_OF_PORTLETS_PER_TAB)] full_tabs = [one_tab for _ in range(BurstConfiguration.nr_of_tabs)] data = {'tab_portlets_list': json.dumps(full_tabs)} result = self.burst_c.portlet_tab_display(**data) selected_portlets = result['portlet_tab_list'] for entry in selected_portlets: self.assertEqual(entry.id, portlet_id) def test_get_configured_portlets_no_session(self): """ Test that if we have no burst stored in session, an empty portlet list is reduced. """ result = self.burst_c.get_configured_portlets() self.assertTrue('portlet_tab_list' in result) self.assertTrue(result['portlet_tab_list'] == []) def test_get_configured_portlets_default(self): """ Check that the default configuration holds one portlet and it's identifier is 'TimeSeries'. """ self.burst_c.index() result = self.burst_c.get_configured_portlets() self.assertTrue('portlet_tab_list' in result) portlets_list = result['portlet_tab_list'] self.assertEqual(len(portlets_list), 1) self.assertTrue(portlets_list[0].algorithm_identifier == 'TimeSeries') def test_get_portlet_session_configuration(self): """ Test that the default portlet session sonciguration is generated as expected, with a default TimeSeries portlet and rest empty. """ self.burst_c.index() result = json.loads(self.burst_c.get_portlet_session_configuration()) portlet_id = dao.get_portlet_by_identifier("TimeSeries").id for tab_idx, tab in enumerate(result): for index_in_tab, value in enumerate(tab): if tab_idx == 0 and index_in_tab == 0: self.assertEqual(value, [portlet_id, "TimeSeries"]) else: self.assertEqual(value, [-1, "None"]) def test_save_parameters_no_relaunch(self): """ Test the save parameters for the default TimeSeries portlet and pass an empty dictionary as the 'new' data. In this case a relaunch should not be required. """ self.burst_c.index() self.assertEqual('noRelaunch', self.burst_c.save_parameters(0, portlet_parameters="{}")) def test_rename_burst(self): """ Create and store a burst, then rename it and check that it works as expected. """ burst = self._store_burst(self.test_project.id, 'started', {'test': 'test'}, 'burst1') self.burst_c.rename_burst(burst.id, "test_new_burst_name") renamed_burst = dao.get_burst_by_id(burst.id) self.assertEqual(renamed_burst.name, "test_new_burst_name") def test_launch_burst(self): """ Launch a burst and check that it finishes correctly and before timeout (100) """ self.burst_c.index() connectivity = self._burst_create_connectivity() launch_params = copy.deepcopy(SIMULATOR_PARAMETERS) launch_params['connectivity'] = connectivity.gid launch_params['simulation_length'] = '10' launch_params = {"simulator_parameters": json.dumps(launch_params)} burst_id = json.loads(self.burst_c.launch_burst("new", "test_burst", **launch_params))['id'] waited = 1 timeout = 100 burst_config = dao.get_burst_by_id(burst_id) while burst_config.status == BurstConfiguration.BURST_RUNNING and waited <= timeout: sleep(0.5) waited += 0.5 burst_config = dao.get_burst_by_id(burst_config.id) if waited > timeout: self.fail("Timed out waiting for simulations to finish.") if burst_config.status != BurstConfiguration.BURST_FINISHED: BurstService().stop_burst(burst_config) self.fail("Burst should have finished successfully.") def test_load_burst(self): """ Test loading and burst and checking you get expected dictionary. """ self.burst_c.index() burst = self._store_burst(self.test_project.id, 'started', {'test': 'test'}, 'burst1') result = json.loads(self.burst_c.load_burst(burst.id)) self.assertEqual(result["status"], "started") self.assertEqual(result['group_gid'], None) self.assertEqual(result['selected_tab'], 0) def test_load_burst_removed(self): """ Add burst to session, then remove burst from database. Try to load burst and check that it will raise exception and remove it from session. """ burst = self._store_burst(self.test_project.id, 'started', {'test': 'test'}, 'burst1') cherrypy.session[common.KEY_BURST_CONFIG] = burst burst_id = burst.id BurstService().cancel_or_remove_burst(burst_id) self.assertRaises(Exception, self.burst_c.load_burst, burst_id) self.assertTrue(common.KEY_BURST_CONFIG not in cherrypy.session) def test_remove_burst_not_session(self): """ Test removing a burst that is not the one currently stored in session. SHould just remove and return a 'done' string. """ burst = self._store_burst(self.test_project.id, 'finished', {'test': 'test'}, 'burst1') cherrypy.session[common.KEY_BURST_CONFIG] = burst another_burst = self._store_burst(self.test_project.id, 'finished', {'test': 'test'}, 'burst1') result = self.burst_c.cancel_or_remove_burst(another_burst.id) self.assertEqual(result, 'done') def test_remove_burst_in_session(self): """ Test that if we remove the burst that is the current one from the session, we get a 'reset-new' string as result. """ burst = self._store_burst(self.test_project.id, 'finished', {'test': 'test'}, 'burst1') cherrypy.session[common.KEY_BURST_CONFIG] = burst result = self.burst_c.cancel_or_remove_burst(burst.id) self.assertEqual(result, 'reset-new') def _store_burst(self, proj_id, status, sim_config, name): """ Create and store a burst entity, for the project given project_id, having the given status and simulator parames config, under the given name. """ burst = BurstConfiguration(proj_id, status, sim_config, name) burst.prepare_before_save() return dao.store_entity(burst) def _burst_create_connectivity(self): """ Create a connectivity that will be used in "non-dummy" burst launches (with the actual simulator). TODO: This is duplicate code from burstservice_test. Should go into the 'generic' DataType factory once that is done. """ meta = {DataTypeMetaData.KEY_SUBJECT: "John Doe", DataTypeMetaData.KEY_STATE: "RAW_DATA"} algorithm = FlowService().get_algorithm_by_module_and_class(SIMULATOR_MODULE, SIMULATOR_CLASS) self.operation = model.Operation(self.test_user.id, self.test_project.id, algorithm.id, json.dumps(''), meta=json.dumps(meta), status=model.STATUS_STARTED) self.operation = dao.store_entity(self.operation) storage_path = FilesHelper().get_project_folder(self.test_project, str(self.operation.id)) connectivity = Connectivity(storage_path=storage_path) connectivity.weights = numpy.ones((74, 74)) connectivity.centres = numpy.ones((74, 3)) adapter_instance = StoreAdapter([connectivity]) OperationService().initiate_prelaunch(self.operation, adapter_instance, {}) return connectivity
class BurstContollerTest(BaseControllersTest): """ Unit tests for burst_controller """ def setUp(self): """ Sets up the environment for testing; creates a `BurstController` """ BaseControllersTest.init(self) self.burst_c = BurstController() def tearDown(self): """ Cleans up the environment after testing is done """ self.cleanup() self.clean_database() def test_index(self): """ Test that index returns a dict with all required keys. Also check that the default portlets are populated, with only the first being the TimeSeries portlet and the rest are empty. """ result_dict = self.burst_c.index() self.assertTrue('burst_list' in result_dict and result_dict['burst_list'] == []) self.assertTrue('available_metrics' in result_dict and isinstance(result_dict['available_metrics'], list)) self.assertTrue('portletList' in result_dict and isinstance(result_dict['portletList'], list)) self.assertEqual(result_dict[common.KEY_SECTION], "burst") self.assertTrue( 'burstConfig' in result_dict and isinstance(result_dict['burstConfig'], BurstConfiguration)) portlets = json.loads(result_dict['selectedPortlets']) portlet_id = dao.get_portlet_by_identifier("TimeSeries").id for tab_idx, tab in enumerate(portlets): for index_in_tab, value in enumerate(tab): if tab_idx == 0 and index_in_tab == 0: self.assertEqual(value, [portlet_id, "TimeSeries"]) else: self.assertEqual(value, [-1, "None"]) self.assertTrue(result_dict['draw_hidden_ranges']) def test_load_burst_history(self): """ Create two burst, load the burst and check that we get back the same stored bursts. """ self._store_burst(self.test_project.id, 'started', {'test': 'test'}, 'burst1') burst = self._store_burst(self.test_project.id, 'started', {'test': 'test'}, 'burst2') cherrypy.session[common.KEY_BURST_CONFIG] = burst result_dict = self.burst_c.load_burst_history() burst_history = result_dict['burst_list'] self.assertEqual(len(burst_history), 2) for burst in burst_history: self.assertTrue(burst.name in ('burst1', 'burst2')) def test_get_selected_burst(self): """ Create burst, add it to session, then check that get_selected_burst return the same burst. Also check that for an unstored entity we get back 'None' """ burst_entity = BurstConfiguration(self.test_project.id, 'started', {}, 'burst1') cherrypy.session[common.KEY_BURST_CONFIG] = burst_entity stored_id = self.burst_c.get_selected_burst() self.assertEqual(stored_id, 'None') burst_entity = dao.store_entity(burst_entity) cherrypy.session[common.KEY_BURST_CONFIG] = burst_entity stored_id = self.burst_c.get_selected_burst() self.assertEqual(str(stored_id), str(burst_entity.id)) def test_get_portlet_configurable_interface(self): """ Look up that an AdapterConfiguration is returned for the default portlet configuration, if we look at index (0, 0) where TimeSeries portlet should be default. """ self.burst_c.index() result = self.burst_c.get_portlet_configurable_interface(0) self.assertTrue(common.KEY_PARAMETERS_CONFIG in result) self.assertFalse(result[common.KEY_PARAMETERS_CONFIG]) adapter_config = result['adapters_list'] # Default TimeSeries portlet should be available, so we expect # adapter_config to be a list of AdapterConfiguration with one element self.assertEqual(len(adapter_config), 1) self.assertTrue(isinstance(adapter_config[0], AdapterConfiguration)) def test_portlet_tab_display(self): """ Update the default portlet configuration, by storing a TimeSeries portlet for all postions. Then check that we get the same configuration. """ self.burst_c.index() portlet_id = dao.get_portlet_by_identifier("TimeSeries").id one_tab = [[portlet_id, "TimeSeries"] for _ in range(NUMBER_OF_PORTLETS_PER_TAB)] full_tabs = [one_tab for _ in range(BurstConfiguration.nr_of_tabs)] data = {'tab_portlets_list': json.dumps(full_tabs)} result = self.burst_c.portlet_tab_display(**data) selected_portlets = result['portlet_tab_list'] for entry in selected_portlets: self.assertEqual(entry.id, portlet_id) def test_get_configured_portlets_no_session(self): """ Test that if we have no burst stored in session, an empty portlet list is reduced. """ result = self.burst_c.get_configured_portlets() self.assertTrue('portlet_tab_list' in result) self.assertTrue(result['portlet_tab_list'] == []) def test_get_configured_portlets_default(self): """ Check that the default configuration holds one portlet and it's identifier is 'TimeSeries'. """ self.burst_c.index() result = self.burst_c.get_configured_portlets() self.assertTrue('portlet_tab_list' in result) portlets_list = result['portlet_tab_list'] self.assertEqual(len(portlets_list), 1) self.assertTrue(portlets_list[0].algorithm_identifier == 'TimeSeries') def test_get_portlet_session_configuration(self): """ Test that the default portlet session sonciguration is generated as expected, with a default TimeSeries portlet and rest empty. """ self.burst_c.index() result = json.loads(self.burst_c.get_portlet_session_configuration()) portlet_id = dao.get_portlet_by_identifier("TimeSeries").id for tab_idx, tab in enumerate(result): for index_in_tab, value in enumerate(tab): if tab_idx == 0 and index_in_tab == 0: self.assertEqual(value, [portlet_id, "TimeSeries"]) else: self.assertEqual(value, [-1, "None"]) def test_save_parameters_no_relaunch(self): """ Test the save parameters for the default TimeSeries portlet and pass an empty dictionary as the 'new' data. In this case a relaunch should not be required. """ self.burst_c.index() self.assertEqual( 'noRelaunch', self.burst_c.save_parameters(0, portlet_parameters="{}")) def test_rename_burst(self): """ Create and store a burst, then rename it and check that it works as expected. """ burst = self._store_burst(self.test_project.id, 'started', {'test': 'test'}, 'burst1') self.burst_c.rename_burst(burst.id, "test_new_burst_name") renamed_burst = dao.get_burst_by_id(burst.id) self.assertEqual(renamed_burst.name, "test_new_burst_name") def test_launch_burst(self): """ Launch a burst and check that it finishes correctly and before timeout (100) """ self.burst_c.index() connectivity = self._burst_create_connectivity() launch_params = copy.deepcopy(SIMULATOR_PARAMETERS) launch_params['connectivity'] = connectivity.gid launch_params['simulation_length'] = '10' launch_params = {"simulator_parameters": json.dumps(launch_params)} burst_id = json.loads( self.burst_c.launch_burst("new", "test_burst", **launch_params))['id'] waited = 1 timeout = 100 burst_config = dao.get_burst_by_id(burst_id) while burst_config.status == BurstConfiguration.BURST_RUNNING and waited <= timeout: sleep(0.5) waited += 0.5 burst_config = dao.get_burst_by_id(burst_config.id) if waited > timeout: self.fail("Timed out waiting for simulations to finish.") if burst_config.status != BurstConfiguration.BURST_FINISHED: BurstService().stop_burst(burst_config) self.fail("Burst should have finished successfully.") def test_load_burst(self): """ Test loading and burst and checking you get expected dictionary. """ self.burst_c.index() burst = self._store_burst(self.test_project.id, 'started', {'test': 'test'}, 'burst1') result = json.loads(self.burst_c.load_burst(burst.id)) self.assertEqual(result["status"], "started") self.assertEqual(result['group_gid'], None) self.assertEqual(result['selected_tab'], 0) def test_load_burst_removed(self): """ Add burst to session, then remove burst from database. Try to load burst and check that it will raise exception and remove it from session. """ burst = self._store_burst(self.test_project.id, 'started', {'test': 'test'}, 'burst1') cherrypy.session[common.KEY_BURST_CONFIG] = burst burst_id = burst.id BurstService().cancel_or_remove_burst(burst_id) self.assertRaises(Exception, self.burst_c.load_burst, burst_id) self.assertTrue(common.KEY_BURST_CONFIG not in cherrypy.session) def test_remove_burst_not_session(self): """ Test removing a burst that is not the one currently stored in session. SHould just remove and return a 'done' string. """ burst = self._store_burst(self.test_project.id, 'finished', {'test': 'test'}, 'burst1') cherrypy.session[common.KEY_BURST_CONFIG] = burst another_burst = self._store_burst(self.test_project.id, 'finished', {'test': 'test'}, 'burst1') result = self.burst_c.cancel_or_remove_burst(another_burst.id) self.assertEqual(result, 'done') def test_remove_burst_in_session(self): """ Test that if we remove the burst that is the current one from the session, we get a 'reset-new' string as result. """ burst = self._store_burst(self.test_project.id, 'finished', {'test': 'test'}, 'burst1') cherrypy.session[common.KEY_BURST_CONFIG] = burst result = self.burst_c.cancel_or_remove_burst(burst.id) self.assertEqual(result, 'reset-new') def _store_burst(self, proj_id, status, sim_config, name): """ Create and store a burst entity, for the project given project_id, having the given status and simulator parames config, under the given name. """ burst = BurstConfiguration(proj_id, status, sim_config, name) burst.prepare_before_save() return dao.store_entity(burst) def _burst_create_connectivity(self): """ Create a connectivity that will be used in "non-dummy" burst launches (with the actual simulator). TODO: This is duplicate code from burstservice_test. Should go into the 'generic' DataType factory once that is done. """ meta = { DataTypeMetaData.KEY_SUBJECT: "John Doe", DataTypeMetaData.KEY_STATE: "RAW_DATA" } algorithm, algo_group = FlowService( ).get_algorithm_by_module_and_class(SIMULATOR_MODULE, SIMULATOR_CLASS) self.operation = model.Operation(self.test_user.id, self.test_project.id, algo_group.id, json.dumps(''), meta=json.dumps(meta), status=model.STATUS_STARTED) self.operation = dao.store_entity(self.operation) storage_path = FilesHelper().get_project_folder( self.test_project, str(self.operation.id)) connectivity = Connectivity(storage_path=storage_path) connectivity.weights = numpy.ones((74, 74)) connectivity.centres = numpy.ones((74, 3)) adapter_instance = StoreAdapter([connectivity]) OperationService().initiate_prelaunch(self.operation, adapter_instance, {}) return connectivity