def test_add_service_as_module__adding_service_with_same_name_errors(): """ Adding a server, as module, with the same name as another service should error. """ inline = InlineServices() inline.add_service_by_module('replyer', import_python_file_from_cwd(REPLYER_PATH)) with pytest.raises(ValueError): inline.add_service_by_module('replyer', import_python_file_from_cwd(REPLYER_PATH))
def test_set_main_service_as_module__adding_second_main_service_throws_error(): """ Adding a second main service, as module, should throw an error. """ inline = InlineServices() inline.add_service_by_module( 'multi_requester', import_python_file_from_cwd(MULTI_REQUESTER_PATH)) with pytest.raises(ValueError): inline.set_main_service_by_module( 'multi_requester', import_python_file_from_cwd(MULTI_REQUESTER_PATH))
def test_set_main_service_as_module__setting_service_with_same_name_errors(): """ Adding a main service, as module, with the same name as another service should error. """ inline = InlineServices() inline.add_service_by_module( 'multi_requester', import_python_file_from_cwd(MULTI_REQUESTER_PATH)) with pytest.raises(ValueError): inline.set_main_service_by_module( 'multi_requester', import_python_file_from_cwd(MULTI_REQUESTER_PATH))
def test_inline_services__services_can_be_run_with_imported_modules(): """ Make sure that services can be run together with inline services provided via modules. """ inline = InlineServices() inline.set_main_service_by_module( 'requester', import_python_file_from_cwd(REQUESTER_PATH)) inline.add_service_by_module('replyer', import_python_file_from_cwd(REPLYER_PATH)) inline.add_relation('requester', 'request', 'replyer', 'reply') inline.start() req_config = inline.get_service_config('requester') assert len(req_config['responses_recieved']) == 2
def test_service__services_can_be_run_with_imported_modules(): """ Make sure the file loglevel and log folder function properly. """ requester_log_path = f'{BASE_LOG_DIR}/requester_with_modules.log' replyer_log_path = f'{BASE_LOG_DIR}/replyer_with_modules.log' requester_module = import_python_file_from_cwd(REQUESTER_PATH) replyer_module = import_python_file_from_cwd(REPLYER_PATH) requester = Service(requester_module, addresses=REQUESTER_ADDRS, config=REQUESTER_CONFIG, log_path=requester_log_path, file_loglevel='DEBUG') replyer = Service(replyer_module, addresses=REPLYER_ADDRS, log_path=replyer_log_path, file_loglevel='DEBUG') replyer.run_service() requester.run_service_as_main() start = time.time() is_success = False while not is_success: if time.time() - start > 1: break if not os.path.exists(requester_log_path): continue with open(requester_log_path, 'r') as requester_log: for line in requester_log.readlines(): if 'GOT ALL RESPONSES' in line: is_success = True replyer.stop_service() # Make sure to stop service! if os.path.exists(requester_log_path): os.remove(requester_log_path) if os.path.exists(replyer_log_path): os.remove(replyer_log_path) if not is_success: raise RuntimeError('Test failed, figure it out!')
def test_service_utils_setup_to_send__workflow_id_constant_on_to_send_calls(): """ Make sure the workflow id does not increment when "increment_id" is False. This will allow services that are in main_mode to not increment the same uuid consistently. """ workflow_id = uuid.uuid4() def check_payload(payload): """ This function is used to validate send payloads have the passed arguments """ assert payload['workflow_id'] == workflow_id return RETURN_PAYLOAD imported_service = utils.import_python_file_from_cwd(SERVICE_PATH) config = {} cur_addresses = utils.get_json_from_rel_path(ADDRESSES_PATH) addresses = service_utils.setup_addresses(cur_addresses, imported_service, config) connections = service_utils.setup_service_connections( addresses, imported_service, config) to_send = service_utils.setup_to_send(connections, {}, workflow_id=workflow_id, increment_id=False) connections['out']['out_connection_1'].send = check_payload for _ in range(4): to_send('out_connection_1', PROPER_ARGS)
def test_service_utils__setup_to_send__workflow_id_put_into_to_send_payload(): """ Make sure if a workflow id is provided it is added to the payload. """ workflow_id = uuid.uuid4() def check_payload(payload): """ This function is used to validate send payloads have the passed arguments """ assert payload['workflow_id'] == workflow_id return RETURN_PAYLOAD imported_service = utils.import_python_file_from_cwd(SERVICE_PATH) config = {} cur_addresses = utils.get_json_from_rel_path(ADDRESSES_PATH) addresses = service_utils.setup_addresses(cur_addresses, imported_service, config) connections = service_utils.setup_service_connections( addresses, imported_service, config) to_send = service_utils.setup_to_send(connections, {}, workflow_id=workflow_id, increment_id=True) connections['out']['out_connection_1'].send = check_payload to_send('out_connection_1', PROPER_ARGS)
def test_service_utils__setup_to_send__args_are_put_into_to_send_payload(): """ Make sure arguments are actually put into the payload """ def check_payload(payload): """ This function is used to validate send payloads have the passed arguments """ if payload['args'] != PROPER_ARGS: raise RuntimeError('Payload does not have args added!!!') return RETURN_PAYLOAD imported_service = utils.import_python_file_from_cwd(SERVICE_PATH) config = {} cur_addresses = utils.get_json_from_rel_path(ADDRESSES_PATH) addresses = service_utils.setup_addresses(cur_addresses, imported_service, config) connections = service_utils.setup_service_connections( addresses, imported_service, config) to_send = service_utils.setup_to_send(connections, {}) connections['out']['out_connection_1'].send = check_payload to_send('out_connection_1', PROPER_ARGS)
def test_service_utils__setup_addresses__with_setup_addresses_func_case(): """ Make sure that the setup addresses func will indeed be called if provided. """ imported_service = utils.import_python_file_from_cwd(SERVICE_PATH) addresses = utils.get_json_from_rel_path(ADDRESSES_PATH) addrs = service_utils.setup_addresses(addresses, imported_service, {}) assert addrs['connections']['in']['in_connection_1']['in_conn_socket_3']
def test_service_utils__setup_config__no_config_model_case(): """ Make sure to return an empty dict if there is no config model in the imported service. (It's optional) """ wo_model_imported_service = utils.import_python_file_from_cwd(WO_SERVICE_PATH) config = service_utils.setup_config({}, wo_model_imported_service) assert config == {}
def test_service_utils__setup_service_connections__no_connection_models_case(): """ Make sure if there's no connection models then an empty dict is returned. """ imported_service = utils.import_python_file_from_cwd(WO_SERVICE_PATH) config = {} conns = service_utils.setup_service_connections(ADDRESSES_PATH, imported_service, config) assert conns == {}
def test_service_utils__setup_addresses__no_setup_addresses_func_case(): """ Make sure not provided setup addresses func in the imported service will not cause an error. (It's optional) """ imported_service_wo_func = utils.import_python_file_from_cwd(WO_SERVICE_PATH) addresses = utils.get_json_from_rel_path(ADDRESSES_PATH) addrs = service_utils.setup_addresses(addresses, imported_service_wo_func, {}) assert addrs['connections']['in']['in_connection_1']['in_conn_socket_1']
def test_inline_services__main_by_module_can_have_provided_config(): """ Make sure that a main service, by module, can have a provided config. """ inline = InlineServices() inline.set_main_service_by_module( 'requester', import_python_file_from_cwd(REQUESTER_PATH), REQUESTER_CONFIG) inline.add_service_by_module( 'replyer', import_python_file_from_cwd(REPLYER_PATH), ) inline.add_relation('requester', 'request', 'replyer', 'reply') inline.start() req_config = inline.get_service_config('requester') assert len(req_config['responses_recieved']) == 4
def test_inline_services__set_main_service_not_providing_a_string_path_throws_error( ): """ Make sure that if setting a main service and accidentally passing a module a ValueError will be thrown. """ inline = InlineServices() with pytest.raises(ValueError): inline.set_main_service('requester', import_python_file_from_cwd(REQUESTER_PATH))
def test_service_utils__setup_config__services_setup_config_functions_properly(): """ Make sure that the service can call setup config prior to the config file being used. """ imported_service = utils.import_python_file_from_cwd(SERVICE_PATH) del imported_service.config_model['required']['env_variable_1'] config = utils.get_json_from_rel_path(CONFIG_PATH) config = service_utils.setup_config(config, imported_service) assert config['optional_1'] == 'optional_value_1' remove_imported_object_module(imported_service)
def test_service_utils__setup_config__config_model_function_needed(): """ Make sure the imported service has a config model. """ imported_service = utils.import_python_file_from_cwd(SERVICE_PATH) del imported_service.config_model config = utils.get_json_from_rel_path(CONFIG_PATH) with pytest.raises(ValueError): config = service_utils.setup_config(config, imported_service) remove_imported_object_module(imported_service)
def test_service_utils__setup_config__config_creation_is_validated(): """ Make sure that the setup config function actually validates what's provided by the config. """ imported_service = utils.import_python_file_from_cwd(SERVICE_PATH) del imported_service.config_model['optional']['config_2'] config = utils.get_json_from_rel_path(CONFIG_PATH) with pytest.raises(ValueError): service_utils.setup_config(config, imported_service)
def test_inline_services__add_service_not_providing_a_string_path_throws_error( ): """ Make sure that if adding a service and accidentally passing a module a ValueError will be thrown. """ inline = InlineServices() with pytest.raises(ValueError): inline.add_service( 'replyer', import_python_file_from_cwd(REPLYER_PATH), )
def test_service_utils__setup_service_connections__connection_models_case(): """ Make sure if there are connection models they are properly loaded. """ imported_service = utils.import_python_file_from_cwd(SERVICE_PATH) config = {} cur_addresses = utils.get_json_from_rel_path(ADDRESSES_PATH) addresses = service_utils.setup_addresses(cur_addresses, imported_service, config) conns = service_utils.setup_service_connections(addresses, imported_service, config) conn = conns['in']['in_connection_1'] assert conn.__class__.__name__ == 'Replyer'
def test_service_utils__setup_service_connections__connection_models_and_setup_conn_models_case( ): """ Make sure setup_service_connections is properly called. """ imported_service = utils.import_python_file_from_cwd(SERVICE_PATH) config = {} cur_addresses = utils.get_json_from_rel_path(ADDRESSES_PATH) addresses = service_utils.setup_addresses(cur_addresses, imported_service, config) conns = service_utils.setup_service_connections(addresses, imported_service, config) conn = conns['out']['out_connection_1'] assert conn.__class__.__name__ == 'Requester'
def test_service_utils__run_init_function__will_properly_call_init_function(): """ Test to make sure that the init_function will be called. """ success = False def set_success_to_true(*_): nonlocal success success = True imported_service = utils.import_python_file_from_cwd(WO_SERVICE_PATH) imported_service.init_function = set_success_to_true service_utils.run_init_function(imported_service, {}, {}, {}) assert success
def set_main_service(self, service_name, rel_service_path, config=None): """ Add the main service to be used. This service will be the initially called service within the inline service function. service_name::str The name of the service to be used for relations rel_service_path::str The relative path to the service from the cwd config::{} The service config passed to the service """ if not isinstance(rel_service_path, str): raise ValueError('Please provided a string for the rel_service_path!') self.set_main_service_by_module( service_name, import_python_file_from_cwd(rel_service_path), config )
def add_service(self, service_name, rel_service_path, config=None): """ Add a service to the inline service object. This service will be called if a relation is set to call it. service_name::str Name of the service to be used for relations rel_service_path::str The relative path to the service from the cwd config::{} The service config passed to the service """ if not isinstance(rel_service_path, str): raise ValueError('Please provided a string for the rel_service_path!') self.add_service_by_module( service_name, import_python_file_from_cwd(rel_service_path), config )
def test_service_utils__setup_to_send__to_send_validates_returned_args_case(): """ Make sure that the return arguments case will also be validated. """ imported_service = utils.import_python_file_from_cwd(SERVICE_PATH) config = {} cur_addresses = utils.get_json_from_rel_path(ADDRESSES_PATH) addresses = service_utils.setup_addresses(cur_addresses, imported_service, config) connections = service_utils.setup_service_connections( addresses, imported_service, config) to_send = service_utils.setup_to_send(connections, {}) connections['out']['out_connection_1'].send = lambda payload: None with pytest.raises(ValueError): to_send('out_connection_1', PROPER_ARGS)
def test_service_utils__setup_to_send__valid_connection_output_type_for_to_send( ): """ Make sure that sending will function if the output type is a connection """ imported_service = utils.import_python_file_from_cwd(SERVICE_PATH) config = {} cur_addresses = utils.get_json_from_rel_path(ADDRESSES_PATH) addresses = service_utils.setup_addresses(cur_addresses, imported_service, config) connections = service_utils.setup_service_connections( addresses, imported_service, config) to_send = service_utils.setup_to_send(connections, {}) out_connection = connections['out']['out_connection_1'] out_connection.args_validator = lambda args: None out_connection.send = lambda payload: RETURN_PAYLOAD to_send('out_connection_1', {})
def test_service_utils__setup_to_send__to_send_returns_proper_args(): """ Make sure the to_send function properly sends arguments and gets the returned arguments back. """ imported_service = utils.import_python_file_from_cwd(SERVICE_PATH) config = {} cur_addresses = utils.get_json_from_rel_path(ADDRESSES_PATH) addresses = service_utils.setup_addresses(cur_addresses, imported_service, config) connections = service_utils.setup_service_connections( addresses, imported_service, config) to_send = service_utils.setup_to_send(connections, {}) connections['out'][ 'out_connection_1'].send = lambda payload: RETURN_PAYLOAD return_arguments = to_send('out_connection_1', PROPER_ARGS) assert return_arguments == RETURN_PAYLOAD['return_args']
def test_service_utils_setup_to_send__workflow_id_incremented_on_to_send_calls( ): """ Make sure the workflow id appends the call number increases with each to_send call. This will allow a developer to more easily debug later down the line. """ workflow_id = uuid.uuid4() call_count = 0 def check_payload(payload): """ This function is used to validate send payloads have the passed arguments """ nonlocal call_count if call_count == 0: assert payload['workflow_id'] == workflow_id else: new_workflow_id = '{}_{}'.format(workflow_id, call_count) assert payload['workflow_id'] == new_workflow_id call_count += 1 return RETURN_PAYLOAD imported_service = utils.import_python_file_from_cwd(SERVICE_PATH) config = {} cur_addresses = utils.get_json_from_rel_path(ADDRESSES_PATH) addresses = service_utils.setup_addresses(cur_addresses, imported_service, config) connections = service_utils.setup_service_connections( addresses, imported_service, config) to_send = service_utils.setup_to_send(connections, {}, workflow_id=workflow_id, increment_id=True) connections['out']['out_connection_1'].send = check_payload for _ in range(4): to_send('out_connection_1', PROPER_ARGS)
def entrance_point( service_definition, config, addresses, logger_args_dict, is_main=False, min_wait_time_s=0): """ service_path::obj Either a string -> to then import the service file or an object itself. addresses = { 'in': { 'connection_name': { 'socket_name': str }, }, 'out': {}, } config = { 'config_1': 'thingy', 'config_2': 12345 } logger_args_dict = { console_loglevel: str, log_path: str, file_loglevel: str, backup_count: int, } """ logging_utils.setup_package_logger(**logger_args_dict) if isinstance(service_definition, str): service_definition = utils.import_python_file_from_cwd(service_definition) config = setup_config(config if config is not None else {}, service_definition) addresses = setup_addresses(addresses, service_definition, config) connections = setup_service_connections(addresses, service_definition, config) setup_sig_handler_funcs( service_definition, config, setup_to_send(connections, logger_args_dict) ) run_init_function(service_definition, connections, config, logger_args_dict) if is_main: run_main( service_definition.main, connections, config, logger_args_dict, min_wait_time_s ) else: run_service( connections, config, logger_args_dict, min_wait_time_s )
def test_service_utils__setup_addresses__no_addresses_path(): """ Make sure an address path does not cause any errors if not provided. """ imported_service = utils.import_python_file_from_cwd(SERVICE_PATH) service_utils.setup_addresses({}, imported_service, {})
def test_service_utils__run_init_function__will_not_fail_if_init_function_not_found(): """ Make sure that if the init_function is not available nothing will blow up. """ imported_service = utils.import_python_file_from_cwd(WO_SERVICE_PATH) service_utils.run_init_function(imported_service, {}, {}, {})