def _handle_er_incomplete_params(method: TEventHandler): # Setup: # ... Create an OE service oe = ObjectExplorerService() oe._service_provider = utils.get_mock_service_provider({}) # ... Create a set of invalid parameters to test param_sets = [ None, ExpandParameters.from_dict({ 'session_id': None, 'node_path': '/' }), ExpandParameters.from_dict({ 'session_id': 'session', 'node_path': None }) ] for params in param_sets: # If: I expand with an invalid set of parameters rc = RequestFlowValidator().add_expected_error( type(None), RequestFlowValidator.basic_error_validation) method(oe, rc.request_context, params) # Then: I should get an error response rc.validate()
def test_generate_uri_missing_params(self): # Setup: Create the parameter sets that will be missing a param each params = [ ConnectionDetails.from_data({ 'host': None, 'dbname': TEST_DBNAME, 'user': TEST_USER, 'port': TEST_PORT }), ConnectionDetails.from_data({ 'host': TEST_HOST, 'dbname': None, 'user': TEST_USER, 'port': TEST_PORT }), ConnectionDetails.from_data({ 'host': TEST_HOST, 'dbname': TEST_DBNAME, 'user': None, 'port': TEST_PORT }), ConnectionDetails.from_data({ 'host': TEST_HOST, 'dbname': TEST_DBNAME, 'user': TEST_USER, 'port': None }) ] for param_set in params: # If: I generate a session URI from params that are missing a value # Then: I should get an exception with self.assertRaises(Exception): ObjectExplorerService._generate_session_uri( param_set, constants.PG_PROVIDER_NAME)
def _preloaded_oe_service( self) -> Tuple[ObjectExplorerService, ObjectExplorerSession, str]: oe = ObjectExplorerService() oe._service_provider = utils.get_mock_service_provider({}) oe._routing_table = PG_ROUTING_TABLE conn_details, session_uri = _connection_details() session = ObjectExplorerSession(session_uri, conn_details) session.server = mock.Mock() session.is_ready = True oe._session_map[session_uri] = session return oe, session, session_uri
def _handle_er_no_session_match(method: TEventHandler): # Setup: Create an OE service oe = ObjectExplorerService() oe._service_provider = utils.get_mock_service_provider({}) # If: I expand a node on a session that doesn't exist rc = RequestFlowValidator().add_expected_error( type(None), RequestFlowValidator.basic_error_validation) params = ExpandParameters.from_dict({ 'session_id': 'session', 'node_path': None }) method(oe, rc.request_context, params) # Then: I should get an error back rc.validate()
def test_handle_create_session_missing_params(self): # Setup: Create an OE service oe = ObjectExplorerService() oe._service_provider = utils.get_mock_service_provider({}) # If: I create an OE session with missing params rc = RequestFlowValidator().add_expected_error( type(None), RequestFlowValidator.basic_error_validation) oe._handle_create_session_request(rc.request_context, None) # Then: # ... I should get an error response rc.validate() # ... A session should not have been created self.assertDictEqual(oe._session_map, {})
def test_create_connection_successful(self): # Setup: mock_connection = MockPGServerConnection() oe = ObjectExplorerService() cs = ConnectionService() cs.connect = mock.MagicMock(return_value=ConnectionCompleteParams()) cs.get_connection = mock.MagicMock(return_value=mock_connection) oe._service_provider = utils.get_mock_service_provider( {constants.CONNECTION_SERVICE_NAME: cs}) params, session_uri = _connection_details() session = ObjectExplorerSession(session_uri, params) connection = oe._create_connection(session, 'foo_database') self.assertIsNotNone(connection) self.assertEqual(connection, mock_connection) cs.connect.assert_called_once() cs.get_connection.assert_called_once()
def test_handle_create_session_successful(self): # Setup: # ... Create OE service with mock connection service that returns a successful connection response mock_connection = MockPGServerConnection(cur=None, host='myserver', name='postgres', user='******', port=123) cs = ConnectionService() cs.connect = mock.MagicMock(return_value=ConnectionCompleteParams()) cs.get_connection = mock.MagicMock(return_value=mock_connection) oe = ObjectExplorerService() oe._service_provider = utils.get_mock_service_provider( {constants.CONNECTION_SERVICE_NAME: cs}) oe._provider = constants.PG_PROVIDER_NAME oe._server = Server # ... Create parameters, session, request context validator params, session_uri = _connection_details() # ... Create validation of success notification def validate_success_notification(response: SessionCreatedParameters): self.assertTrue(response.success) self.assertEqual(response.session_id, session_uri) self.assertIsNone(response.error_message) self.assertIsInstance(response.root_node, NodeInfo) self.assertEqual(response.root_node.label, TEST_DBNAME) self.assertEqual(response.root_node.node_path, session_uri) self.assertEqual(response.root_node.node_type, 'Database') self.assertIsInstance(response.root_node.metadata, ObjectMetadata) self.assertEqual(response.root_node.metadata.urn, oe._session_map[session_uri].server.urn_base) self.assertEqual( response.root_node.metadata.name, oe._session_map[session_uri].server.maintenance_db_name) self.assertEqual(response.root_node.metadata.metadata_type_name, 'Database') self.assertFalse(response.root_node.is_leaf) rc = RequestFlowValidator() rc.add_expected_response( CreateSessionResponse, lambda param: self.assertEqual(param.session_id, session_uri)) rc.add_expected_notification(SessionCreatedParameters, SESSION_CREATED_METHOD, validate_success_notification) # If: I create a session oe._handle_create_session_request(rc.request_context, params) oe._session_map[session_uri].init_task.join() # Then: # ... Error notification should have been returned, session should be cleaned up from OE service rc.validate() # ... The session should still exist and should have connection and server setup self.assertIn(session_uri, oe._session_map) self.assertIsInstance(oe._session_map[session_uri].server, Server) self.assertTrue(oe._session_map[session_uri].is_ready)
def test_create_connection_failed(self): # Setup: oe = ObjectExplorerService() cs = ConnectionService() connect_response = ConnectionCompleteParams() error = 'Failed' connect_response.error_message = error cs.connect = mock.MagicMock(return_value=connect_response) oe._service_provider = utils.get_mock_service_provider( {constants.CONNECTION_SERVICE_NAME: cs}) params, session_uri = _connection_details() session = ObjectExplorerSession(session_uri, params) with self.assertRaises(RuntimeError) as context: oe._create_connection(session, 'foo_database') self.assertEqual(error, str(context.exception)) cs.connect.assert_called_once()
def test_init(self): # If: I create a new OE service oe = ObjectExplorerService() # Then: # ... The service should have its internal state initialized self.assertIsNone(oe._service_provider) self.assertDictEqual(oe._session_map, {}) self.assertIsNotNone(oe._session_lock)
def test_handle_create_session_incomplete_params(self): # Setup: Create an OE service oe = ObjectExplorerService() oe._service_provider = utils.get_mock_service_provider({}) # If: I create an OE session for with missing params # NOTE: We only need to get the generate uri method to throw, we make sure it throws in all # scenarios in a different test rc = RequestFlowValidator().add_expected_error( type(None), RequestFlowValidator.basic_error_validation) params = ConnectionDetails.from_data({}) oe._handle_create_session_request(rc.request_context, params) # Then: # ... I should get an error response rc.validate() # ... A session should not have been created self.assertDictEqual(oe._session_map, {})
def _connection_details() -> Tuple[ConnectionDetails, str]: param = ConnectionDetails() param.options = { 'host': TEST_HOST, 'dbname': TEST_DBNAME, 'user': TEST_USER, 'port': TEST_PORT } session_uri = ObjectExplorerService._generate_session_uri( param, constants.PG_PROVIDER_NAME) return param, session_uri
def setUp(self): # Setup: Create an OE service and add a session to it self.cs = ConnectionService() self.mock_connection = {} self.oe = ObjectExplorerService() params, session_uri = _connection_details() self.session = ObjectExplorerSession(session_uri, params) self.oe._session_map[session_uri] = self.session name = 'dbname' self.mock_server = Server(MockPGServerConnection()) self.session.server = self.mock_server self.db = Database(self.mock_server, name) self.db._connection = self.mock_server._conn self.session.server._child_objects[Database.__name__] = [self.db] self.cs.get_connection = mock.MagicMock( return_value=self.mock_connection) self.cs.disconnect = mock.MagicMock(return_value=True) self.oe._service_provider = utils.get_mock_service_provider( {constants.CONNECTION_SERVICE_NAME: self.cs})
def test_register(self): # Setup: # ... Create a mock service provider server: JSONRPCServer = JSONRPCServer(None, None) server.set_notification_handler = mock.MagicMock() server.set_request_handler = mock.MagicMock() sp: ServiceProvider = ServiceProvider(server, {}, constants.PG_PROVIDER_NAME, utils.get_mock_logger()) # If: I register a OE service oe = ObjectExplorerService() oe.register(sp) # Then: # ... The service should have registered its request handlers server.set_request_handler.assert_called() server.set_notification_handler.assert_not_called() # ... The service provider should have been stored self.assertIs(oe._service_provider, sp)
def test_handle_create_session_threading_fail(self): # Setup: # ... Create an OE service oe = ObjectExplorerService() oe._service_provider = utils.get_mock_service_provider({}) oe._provider = constants.PG_PROVIDER_NAME # ... Patch the threading to throw patch_mock = mock.MagicMock(side_effect=Exception('Boom!')) patch_path = 'ossdbtoolsservice.object_explorer.object_explorer_service.threading.Thread' with mock.patch(patch_path, patch_mock): # If: I create a new session params, session_uri = _connection_details() rc = RequestFlowValidator() rc.add_expected_response( CreateSessionResponse, lambda param: self.assertEqual(param.session_id, session_uri)) rc.add_expected_notification( SessionCreatedParameters, SESSION_CREATED_METHOD, lambda param: self._validate_init_error(param, session_uri)) oe._handle_create_session_request(rc.request_context, params) # Then: # ... The error notification should have been returned rc.validate() # ... The session should have been cleaned up self.assertDictEqual(oe._session_map, {})
def test_init_session_failed_connection(self): # Setup: # ... Create OE service with mock connection service that returns a failed connection response cs = ConnectionService() connect_response = ConnectionCompleteParams() connect_response.error_message = 'Boom!' cs.connect = mock.MagicMock(return_value=connect_response) oe = ObjectExplorerService() oe._service_provider = utils.get_mock_service_provider( {constants.CONNECTION_SERVICE_NAME: cs}) # If: I initialize a session (NOTE: We're bypassing request handler to avoid threading issues) params, session_uri = _connection_details() session = ObjectExplorerSession(session_uri, params) oe._session_map[session_uri] = session rc = RequestFlowValidator() rc.add_expected_notification( SessionCreatedParameters, SESSION_CREATED_METHOD, lambda param: self._validate_init_error(param, session_uri)) oe._initialize_session(rc.request_context, session) # Then: # ... Error notification should have been returned, session should be cleaned up from OE service rc.validate() self.assertDictEqual(oe._session_map, {})
def test_generate_uri_valid_params(self): # If: I generate a session URI from a valid connection details object params, session_uri = _connection_details() output = ObjectExplorerService._generate_session_uri( params, constants.PG_PROVIDER_NAME) # Then: The output should be a properly formed URI parse_result = url_parse.urlparse(output) self.assertEqual(parse_result.scheme, 'objectexplorer') self.assertTrue(parse_result.netloc) re_match = re.match( r'(?P<username>\w+)@(?P<host>\w+):(?P<port>\w+):(?P<db_name>\w+)', parse_result.netloc) self.assertIsNotNone(re_match) self.assertEqual(re_match.group('username'), TEST_USER) self.assertEqual(re_match.group('host'), TEST_HOST) self.assertEqual(int(re_match.group('port')), TEST_PORT) self.assertEqual(re_match.group('db_name'), TEST_DBNAME)
def test_handle_create_session_session_exists(self): # Setup: Create an OE service and pre-load a session oe = ObjectExplorerService() oe._service_provider = utils.get_mock_service_provider({}) params, session_uri = _connection_details() session = ObjectExplorerSession(session_uri, params) oe._session_map[session_uri] = session oe._provider = constants.PG_PROVIDER_NAME # If: I attempt to create an OE session that already exists rc = RequestFlowValidator().add_expected_response( bool, self.assertFalse) oe._handle_create_session_request(rc.request_context, params) # Then: # ... I should get a response as False rc.validate() # ... The old session should remain self.assertIs(oe._session_map[session_uri], session)
class SessionTestCase(unittest.TestCase): TEST_HOST = 'testhost' TEST_DBNAME = 'testdb' TEST_USER = '******' TEST_PASSWORD = '******' def setUp(self): # Setup: Create an OE service and add a session to it self.cs = ConnectionService() self.mock_connection = {} self.oe = ObjectExplorerService() params, session_uri = _connection_details() self.session = ObjectExplorerSession(session_uri, params) self.oe._session_map[session_uri] = self.session name = 'dbname' self.mock_server = Server(MockPGServerConnection()) self.session.server = self.mock_server self.db = Database(self.mock_server, name) self.db._connection = self.mock_server._conn self.session.server._child_objects[Database.__name__] = [self.db] self.cs.get_connection = mock.MagicMock( return_value=self.mock_connection) self.cs.disconnect = mock.MagicMock(return_value=True) self.oe._service_provider = utils.get_mock_service_provider( {constants.CONNECTION_SERVICE_NAME: self.cs}) # CLOSE SESSION ######################################################## def test_handle_close_session_missing_params(self): # If: I close an OE session with missing params rc = RequestFlowValidator().add_expected_error( type(None), RequestFlowValidator.basic_error_validation) self.oe._handle_close_session_request(rc.request_context, None) # Then: I should get an error response rc.validate() def test_handle_close_session_incomplete_params(self): # If: I close an OE session for with missing params # NOTE: We only need to get the generate uri method to throw, we make sure it throws in all # scenarios in a different test rc = RequestFlowValidator().add_expected_error( type(None), RequestFlowValidator.basic_error_validation) params = ConnectionDetails.from_data({}) self.oe._handle_close_session_request(rc.request_context, params) # Then: # ... I should get an error response rc.validate() def test_handle_close_session_nosession(self): # Setup: Create an empty session dictionary self.oe._session_map = {} # If: I close an OE session that doesn't exist rc = RequestFlowValidator().add_expected_response( bool, self.assertFalse) session_id = _connection_details()[1] params = _close_session_params() params.session_id = session_id self.oe._handle_close_session_request(rc.request_context, params) # Then: I should get a successful response rc.validate() def test_handle_close_session_unsuccessful(self): self.cs.disconnect = mock.MagicMock(return_value=False) # If: I close an OE session that doesn't exist rc = RequestFlowValidator().add_expected_response( bool, self.assertFalse) session_id = _connection_details()[1] params = _close_session_params() params.session_id = session_id self.oe._handle_close_session_request(rc.request_context, params) # Then: I should get a successful response rc.validate() self.oe._service_provider.logger.info.assert_called_with( 'Could not close the OE session with Id objectexplorer://testuser@testhost:5432:testdb/' ) def test_handle_close_session_throwsException(self): # setup to throw exception on disconnect self.cs.disconnect = mock.MagicMock(side_effect=Exception) # If: I close an OE session that doesn't exist rc = RequestFlowValidator().add_expected_error(type(None)) session_id = _connection_details()[1] params = _close_session_params() params.session_id = session_id self.oe._handle_close_session_request(rc.request_context, params) # Then: I should get a successful response rc.validate() self.oe._service_provider.logger.error.assert_called_once() def test_handle_close_session_successful(self): # If: I close a session rc = RequestFlowValidator().add_expected_response( bool, self.assertTrue) session_id = _connection_details()[1] params = _close_session_params() params.session_id = session_id self.oe._handle_close_session_request(rc.request_context, params) # Then: # ... I should get a successful response rc.validate() # ... The session should no longer be in the self.assertDictEqual(self.oe._session_map, {}) # SHUTDOWN NODE ######################################################### def test_handle_shutdown_successfulWithSessions(self): # shutdown the session self.oe._handle_shutdown() self.oe._service_provider.logger.info.assert_called_with( 'Closed the OE session with Id: objectexplorer://testuser@testhost:5432:testdb/' ) def test_handle_shutdown_successfulNoDatabase(self): # Setup: Create an OE service and add a session to it self.session.server._child_objects[Database.__name__] = [] # shutdown the session self.oe._handle_shutdown() self.oe._service_provider.logger.info.assert_called_with( 'Closed the OE session with Id: objectexplorer://testuser@testhost:5432:testdb/' ) def test_handle_shutdown_UnsuccessfulWithSessions(self): # Setup: Create an OE service and add a session to it self.cs.disconnect = mock.MagicMock(return_value=False) # shutdown the session self.oe._handle_shutdown() self.oe._service_provider.logger.info.assert_called_with( 'Could not close the OE session with Id: objectexplorer://testuser@testhost:5432:testdb/' ) def test_handle_shutdown_successfulNoSessions(self): # Setup: Create an empty session dictionary self.oe._session_map = {} # shutdown the session self.oe._handle_shutdown() self.oe._service_provider.logger.info.assert_called_with( 'Closing all the OE sessions')
class TestObjectExplorerRouting(unittest.TestCase): def setUp(self): service_provider = ServiceProvider(None, {}, PG_PROVIDER_NAME) self.object_explorer_service = ObjectExplorerService() self.object_explorer_service.service_provider = service_provider self.object_explorer_service._routing_table = PG_ROUTING_TABLE # FOLDER TESTING ####################################################### def test_folder_init(self): # If: I create a folder label = 'FolderName' path = 'folder_path' folder = session.Folder(label, path) # Then: The internal state of the folder should be set up properly self.assertEqual(folder.path, path + '/') self.assertEqual(folder.label, label) def test_folder_as_node(self): # If: I have a folder and ask for it to be turned into a node label = 'FolderName' path = 'folder_path' current_path = '/' node = session.Folder(label, path).as_node(current_path) # Then: The node state should be setup properly self.assertIsInstance(node, NodeInfo) self.assertFalse(node.is_leaf) self.assertEqual(node.label, label) self.assertIsNotNone(urlparse(node.node_path)) self.assertTrue(node.node_path.endswith('/')) self.assertEqual(node.node_type, 'Folder') # ROUTING TARGET TESTS ################################################# def test_routing_target_init_no_folders(self): # If: I create a routing target without any folders defined node_generator = mock.MagicMock() rt = session.RoutingTarget(None, node_generator) # Then: The internal state should show an empty array of folders self.assertListEqual(rt.folders, []) self.assertIs(rt.node_generator, node_generator) def test_routing_target_init_with_folders(self): # If: I create a routing target with folders defined node_generator = mock.MagicMock() folder_list = [session.Folder('FolderName', 'folder_path')] rt = session.RoutingTarget(folder_list, node_generator) # Then: The internal state should reflect a list of folders being provided self.assertIs(rt.folders, folder_list) self.assertIs(rt.node_generator, node_generator) def test_routing_target_get_nodes_empty(self): # If: I ask for nodes for an empty routing target rt = session.RoutingTarget(None, None) output = rt.get_nodes( False, '/', ObjectExplorerSession('session_id', ConnectionDetails()), {}) # Then: The results should be empty self.assertListEqual(output, []) def test_routing_target_get_nodes_not_empty(self): # Setup: Create mock node generator and folder node list node1 = NodeInfo() node2 = NodeInfo() node_generator = mock.MagicMock(return_value=[node1, node2]) folder_list = [ session.Folder('Folder1', 'fp1'), session.Folder('Folder2', 'fp2') ] # If: I ask for nodes for a routing target rt = session.RoutingTarget(folder_list, node_generator) current_path = '/' match_params = {} object_explorer_session = ObjectExplorerSession( 'session_id', ConnectionDetails()) output = rt.get_nodes(False, current_path, object_explorer_session, match_params) # Then: # ... I should get back a list of nodes self.assertIsInstance(output, list) for node in output: self.assertIsInstance(node, NodeInfo) self.assertEqual(len(output), 4) self.assertEqual(output[0].node_type, 'Folder') self.assertEqual(output[1].node_type, 'Folder') self.assertIs(output[2], node1) self.assertIs(output[3], node2) # ... The node generator should have been called node_generator.assert_called_once_with(False, current_path, object_explorer_session, match_params) # ROUTING TABLE TESTS ################################################## def test_routing_table(self): # Make sure that all keys in the routing table are regular expressions # Make sure that all items in the routing table are RoutingTargets re_class = re.compile('^/$').__class__ for key, item in PG_ROUTING_TABLE.items(): self.assertIsInstance(key, re_class) self.assertIsInstance(item, session.RoutingTarget) def test_routing_invalid_path(self): # If: Ask to route a path without a route # Then: I should get an exception with self.assertRaises(ValueError): self.object_explorer_service._route_request( False, ObjectExplorerSession('session_id', ConnectionDetails()), '!/invalid!/') def test_routing_match(self): # If: Ask to route a request that is valid output = self.object_explorer_service._route_request( False, ObjectExplorerSession('session_id', ConnectionDetails()), '/') # Then: The output should be a list of nodes self.assertIsInstance(output, list) for node in output: self.assertIsInstance(node, NodeInfo)
def setUp(self): service_provider = ServiceProvider(None, {}, PG_PROVIDER_NAME) self.object_explorer_service = ObjectExplorerService() self.object_explorer_service.service_provider = service_provider self.object_explorer_service._routing_table = PG_ROUTING_TABLE
def refresh_method(oe: ObjectExplorerService, rc: RequestContext, p: ExpandParameters): oe._handle_refresh_request(rc, p)