def test_simple_algorithm_result(input_file: str, algorithm: str, expected_file: str, optional_param: str): """ Testing given algorithm on given input and comparing the result with expected output. .. note:: Bare on mind that this function is heavily testing comparison. If this test fails, don't forget to check also comparison function and wrapper! :param input_file: path to XML file containing input :param algorithm: algorithm to be run :param expected_file: path to XML file containing expected output :param optional_param: extra parameter for algorithms that need it (currently only regexp derivation and CYK) """ xml_input = read_input(input_file) expected_output = read_input(expected_file) json_input = XMLConverter.xml_to_json(xml_input) json_output = XMLConverter.xml_to_json(expected_output) result = logic_layer.simple_algorithm(json_input, algorithm) to_compare = {'lhs': result, 'rhs': json_output} res = logic_layer.comparison(to_compare) assert res['result'] is True
def test_fails(): """ Testing invalid requests for :mod:`~backend.logic_layer` that should always fail. """ # Passing invalid name of algorithm json_input = XMLConverter.xml_to_json(read_input(REGEXPS + '/regexp.xml')) res = logic_layer.simple_algorithm(json_input, 'regexp_trimmm') assert res['exception'] == 'Unknown algorithm passed as parameter!' assert res['type'] is AltInterfaceException # Omitting the optional parameter which is mandatory for some algorithms res = logic_layer.simple_algorithm(json_input, AlgorithmTypes.REGEXP_DERIVATION) assert res['exception'] == 'Invalid JSON structure' assert res['type'] is XMLConverter.JSONDecodeError # Passing invalid input type res = logic_layer.simple_algorithm( json_input, AlgorithmTypes.AUTOMATON_DETERMINIZATION) assert 'Entry overload' in res['exception'] assert 'not available' in res['exception'] assert res['type'] is AltInterfaceException # Missing 'target' in transformation input res = logic_layer.transformation(json_input) assert res['exception'] == 'Invalid JSON structure' assert res['type'] is XMLConverter.JSONDecodeError # Passing invalid target type to transformation json_input_transformation = {'source': json_input, 'target': 'NFA'} res = logic_layer.transformation(json_input_transformation) assert res['exception'] == 'Unknown \'to\' parameter passed as parameter!' assert res['type'] is AltInterfaceException # Trying to convert ENFA to RG json_input = XMLConverter.xml_to_json( read_input(AUTOMATA + '/ENFA1.EPSILON.xml')) json_input_transformation = {'source': json_input, 'target': 'rg'} res = logic_layer.transformation(json_input_transformation) assert 'Entry overload' in res['exception'] assert 'not available' in res['exception'] assert res['type'] is AltInterfaceException # Trying to compare FA and CFG json_input2 = XMLConverter.xml_to_json( read_input(GRAMMARS + '/CFG1.UNIT.xml')) json_input_comparison = {'lhs': json_input, 'rhs': json_input2} res = logic_layer.comparison(json_input_comparison) assert 'Entry overload' in res['exception'] assert 'not available' in res['exception'] assert res['type'] is AltInterfaceException
def test_recursion_cnf_result(input_file: str, algorithm: str, expected_file: str): xml_input = read_input(input_file) expected_output = read_input(expected_file) json_input = XMLConverter.xml_to_json(xml_input) expected_json = XMLConverter.xml_to_json(expected_output) result = logic_layer.simple_algorithm(json_input, algorithm) to_compare = {'lhs': result['result'], 'rhs': expected_json} assert result['result'] == expected_json res = logic_layer.comparison(to_compare) assert res['result'] is True
def comparison(json_file: dict) -> dict: """ Logic layer function for calling correct JSON/XML conversion, running the comparison through our Python ALT interface and converting result back to JSON for REST API. :param json_file: `dictionary` containing the input :return: `dictionary` containing the output of comparison (true or false) OR `dictionary` with exception message \ and exception type """ try: lhs, lhs_type, rhs, rhs_type = Converter.json_to_xml( json_file, AlgorithmTypes.COMPARISON) with AltInterface() as interface: algorithm_result = interface.comparison(lhs, lhs_type, rhs, rhs_type) result = Converter.xml_to_json(algorithm_result, AlgorithmTypes.COMPARISON) return result except (AltInterfaceException, Converter.JSONDecodeError, Converter.XMLDecodeError) as e: return {'exception': e.msg, 'type': e.exc_type}
def test_recursion_cnf_run(input_file: str, algorithm: str, result_type: str): json_input = XMLConverter.xml_to_json(read_input(input_file)) res = logic_layer.simple_algorithm(json_input, algorithm) assert 'after_reduction' in res.keys() assert 'after_epsilon' in res.keys() assert 'after_unit_rules' in res.keys() assert result_type == res['result']['type']
def test_derivation_result(input_file: str, expected_file: str, optional_param: str): xml_input = read_input(input_file) expected_output = read_input(expected_file) json_input = XMLConverter.xml_to_json(xml_input) json_output = XMLConverter.xml_to_json(expected_output) json_input = {'regexp': json_input, 'derivation_string': optional_param} result = logic_layer.simple_algorithm(json_input, AlgorithmTypes.REGEXP_DERIVATION) result = result['steps'][-1] to_compare = {'lhs': result, 'rhs': json_output} res = logic_layer.comparison(to_compare) assert res['result'] is True
def transformation(json_file: dict) -> dict: """ Logic layer function for calling correct JSON/XML conversion, running the transformation through our Python ALT interface and converting result back to JSON for REST API. :param json_file: `dictionary` containing the input (finite automaton, regular grammar or regexp) :return: `dictionary` containing the output of transformation (finite automaton, regular grammar or regexp) OR \ `dictionary` with exception message and exception type """ try: source, source_type, target_type = Converter.json_to_xml( json_file, AlgorithmTypes.TRANSFORMATION) with AltInterface() as interface: algorithm_result = interface.conversion(source, source_type, target_type) result = Converter.xml_to_json(algorithm_result, AlgorithmTypes.TRANSFORMATION) return result except (AltInterfaceException, Converter.JSONDecodeError, Converter.XMLDecodeError) as e: return {'exception': e.msg, 'type': e.exc_type}
def test_cyk_run(input_file: str, result_type: str, optional_param: str): json_input = XMLConverter.xml_to_json(read_input(input_file)) json_input = {'grammar': json_input, 'cyk_string': optional_param} res = logic_layer.simple_algorithm(json_input, AlgorithmTypes.GRAMMAR_CYK) assert 'step_table' in res.keys() assert 'result' in res.keys() assert res['result'] is True or res['result'] is False
def test_cyk_result(input_file: str, expected_file: str, expected_file_table: str, optional_param: str): xml_input = read_input(input_file) expected_output = read_input(expected_file) expected_output_table = read_input(expected_file_table) json_input = XMLConverter.xml_to_json(xml_input) expected_json = XMLConverter.xml_to_json(expected_output, AlgorithmTypes.GRAMMAR_CYK, steps=expected_output_table) json_input = {'grammar': json_input, 'cyk_string': optional_param} result = logic_layer.simple_algorithm(json_input, AlgorithmTypes.GRAMMAR_CYK) assert result['result'] == expected_json['result'] assert result['step_table'] == expected_json['step_table']
def test_derivation_run(input_file: str, result_type: str, optional_param: str): json_input = XMLConverter.xml_to_json(read_input(input_file)) json_input = {'regexp': json_input, 'derivation_string': optional_param} res = logic_layer.simple_algorithm(json_input, AlgorithmTypes.REGEXP_DERIVATION) assert 'steps' in res.keys() assert 'trimmed_steps' in res.keys() assert result_type == res['steps'][-1]['type']
def test_minimization_result(input_file: str, expected_file: str, expected_file_table: str): xml_input = read_input(input_file) expected_output = read_input(expected_file) expected_output_table = read_input(expected_file_table) json_input = XMLConverter.xml_to_json(xml_input) expected_json = XMLConverter.xml_to_json( expected_output, AlgorithmTypes.AUTOMATON_MINIMIZATION, steps=expected_output_table) result = logic_layer.simple_algorithm( json_input, AlgorithmTypes.AUTOMATON_MINIMIZATION) to_compare = {'lhs': result['result'], 'rhs': expected_json['result']} res = logic_layer.comparison(to_compare) assert res['result'] is True assert result['steps'] == expected_json['steps']
def test_comparison(input_file: str): """ Basic comparison test. Takes input and compares it with itself. :param input_file: path to XML file containing input """ xml_input = XMLConverter.xml_to_json(read_input(input_file)) json_file = {'lhs': xml_input, 'rhs': xml_input} res = logic_layer.comparison(json_file) assert res['result'] is True
def _automaton_minimization(json_file: dict) -> dict: try: source = Converter.json_to_xml(json_file, AlgorithmTypes.AUTOMATON_MINIMIZATION) with AltInterface() as interface: algorithm_steps = interface.algorithms( source, AlgorithmTypes.AUTOMATON_MINIMIZATION) algorithm_result = interface.algorithms( source, AlgorithmTypes.AUTOMATON_MINIMIZATION_NO_VERBOSE) result = Converter.xml_to_json(algorithm_result, AlgorithmTypes.AUTOMATON_MINIMIZATION, steps=algorithm_steps) return result except (AltInterfaceException, Converter.JSONDecodeError, Converter.XMLDecodeError) as e: return {'exception': e.msg, 'type': e.exc_type}
def _grammar_cyk(json_file: dict) -> dict: try: cyk_string, source = Converter.json_to_xml(json_file, AlgorithmTypes.GRAMMAR_CYK) with AltInterface() as interface: algorithm_steps = interface.algorithms(source, AlgorithmTypes.GRAMMAR_CYK, cyk_string) algorithm_result = interface.algorithms( source, AlgorithmTypes.GRAMMAR_CYK_NO_VERBOSE, cyk_string) result = Converter.xml_to_json(algorithm_result, AlgorithmTypes.GRAMMAR_CYK, steps=algorithm_steps) return result except (AltInterfaceException, Converter.JSONDecodeError, Converter.XMLDecodeError) as e: return {'exception': e.msg, 'type': e.exc_type}
def test_epsilon_trim_det_min(automaton: str): """ Testing sequence of automata algorithms: epsilon transition removal, automaton trim, determinization and minimization. In each step checking for valid output type. :param automaton: path to XML file containing input automaton """ res = XMLConverter.xml_to_json(read_input(automaton)) for algorithm, result_type in [ (AlgorithmTypes.AUTOMATON_EPSILON_REMOVAL, 'NFA'), (AlgorithmTypes.AUTOMATON_TRIM, 'NFA'), (AlgorithmTypes.AUTOMATON_DETERMINIZATION, 'DFA'), (AlgorithmTypes.AUTOMATON_MINIMIZATION_NO_VERBOSE, 'DFA') ]: res = logic_layer.simple_algorithm(res, algorithm) assert result_type == res['type']
def test_simple_algorithm_run(input_file: str, algorithm: str, result_type: str, optional_param: str): """ Simple algorithms test. Just run the given algorithm with given input and checks the output type. :param input_file: path to XML file containing input :param algorithm: algorithm to be run :param result_type: expected type of the output :param optional_param: extra parameter for algorithms that need it (currently only regexp derivation and CYK) """ json_input = XMLConverter.xml_to_json(read_input(input_file)) res = logic_layer.simple_algorithm(json_input, algorithm) if algorithm == AlgorithmTypes.AUTOMATON_MINIMIZATION: assert 'steps' in res.keys() assert result_type == res['result']['type'] else: assert result_type == res['type']
def _grammar_left_recursion(json_file: dict) -> dict: """ Logic layer function for calling correct JSON/XML conversion, running the left recursion removal through our Python\ ALT interface and converting the result back to JSON for REST API. :param json_file: `dictionary` containing the input (context-free grammar) :return: `dictionary` containing the output of left recursion removal (context-free grammar without left recursion)\ OR `dictionary` with exception message and exception type """ try: source = Converter.json_to_xml( json_file, AlgorithmTypes.GRAMMAR_LEFT_RECURSION_REMOVAL) # Calling left recursion removal in four steps, saving steps in an array with AltInterface() as interface: after_reduction = interface.algorithms( source, AlgorithmTypes.GRAMMAR_REDUCTION) after_epsilon = interface.algorithms( after_reduction, AlgorithmTypes.GRAMMAR_EPSILON_REMOVAL) after_unit = interface.algorithms( after_epsilon, AlgorithmTypes.GRAMMAR_UNIT_RULES_REMOVAL) after_recursion = interface.algorithms( after_unit, AlgorithmTypes.GRAMMAR_LEFT_RECURSION_REMOVAL) algorithm_steps = { 'after_reduction': after_reduction, 'after_epsilon': after_epsilon, 'after_unit': after_unit } result = Converter.xml_to_json( after_recursion, AlgorithmTypes.GRAMMAR_LEFT_RECURSION_REMOVAL, steps=algorithm_steps) return result except (AltInterfaceException, Converter.JSONDecodeError, Converter.XMLDecodeError) as e: return {'exception': e.msg, 'type': e.exc_type}
def _grammar_cnf(json_file: dict) -> dict: """ Logic layer function for calling correct JSON/XML conversion, running the CNF conversion through our Python ALT interface and converting the result back to JSON for REST API. :param json_file: `dictionary` containing the input (context-free grammar) :return: `dictionary` containing the output of CNF conversion (context-free grammar in CNF) OR `dictionary` with \ exception message and exception type """ try: source = Converter.json_to_xml(json_file, AlgorithmTypes.GRAMMAR_CNF_CONVERSION) # Calling CNF transformation in four steps (following BI-AAG practice), saving steps in an array with AltInterface() as interface: after_reduction = interface.algorithms( source, AlgorithmTypes.GRAMMAR_REDUCTION) after_epsilon = interface.algorithms( after_reduction, AlgorithmTypes.GRAMMAR_EPSILON_REMOVAL) after_unit = interface.algorithms( after_epsilon, AlgorithmTypes.GRAMMAR_UNIT_RULES_REMOVAL) after_cnf = interface.algorithms( after_unit, AlgorithmTypes.GRAMMAR_CNF_CONVERSION) algorithm_steps = { 'after_reduction': after_reduction, 'after_epsilon': after_epsilon, 'after_unit': after_unit, } result = Converter.xml_to_json(after_cnf, AlgorithmTypes.GRAMMAR_CNF_CONVERSION, steps=algorithm_steps) return result except (AltInterfaceException, Converter.JSONDecodeError, Converter.XMLDecodeError) as e: return {'exception': e.msg, 'type': e.exc_type}
def test_transformation(input_file: str, source: str, target: str): """ Simple conversion test. Converts input to `target`, checks the output type, converts it back to `source` and compare it with original input. .. note:: Bare on mind that this function is also slightly testing comparison. If this test fails, don't forget to check also comparison function and wrapper! :param input_file: path to XML file containing input :param source: type of input :param target: type of conversion output """ if target == 'fa': result_type = 'NFA' elif target == 'rg': result_type = 'RightRG' elif target == 're': result_type = 'UnboundedRegExp' else: pytest.fail('Invalid target passed as argument!!') return xml_input = XMLConverter.xml_to_json(read_input(input_file)) json_file = {'target': target, 'source': xml_input} # Converting to target res = logic_layer.transformation(json_file) assert result_type == res['type'] json_file = {'target': source, 'source': res} # Converting back to source res = logic_layer.transformation(json_file) json_file = {'lhs': res, 'rhs': xml_input} res = logic_layer.comparison(json_file) assert res['result'] is True
def _regexp_derivation(json_file: dict) -> dict: """ Logic layer function for calling correct JSON/XML conversion, running the derivation through our Python ALT interface and converting the result back to JSON for REST API. :param json_file: `dictionary` containing the input (regexp and derivation string) :return: `dictionary` containing the output of derivation (result, steps and trimmed_Steps) OR `dictionary` with \ exception message and exception type """ try: derivation_string, source = Converter.json_to_xml( json_file, AlgorithmTypes.REGEXP_DERIVATION) algorithm_steps = [] trimmed_algorithm_steps = [] # Derivation of regexp is called separately for each character of derivation string with AltInterface() as interface: for c in derivation_string: source = interface.algorithms(source, AlgorithmTypes.REGEXP_DERIVATION, c) algorithm_steps.append(source) source = interface.algorithms(source, AlgorithmTypes.REGEXP_TRIM) trimmed_algorithm_steps.append(source) result = Converter.xml_to_json(None, AlgorithmTypes.REGEXP_DERIVATION, steps=algorithm_steps, trimmed_steps=trimmed_algorithm_steps) return result except (AltInterfaceException, Converter.JSONDecodeError, Converter.XMLDecodeError) as e: return {'exception': e.msg, 'type': e.exc_type}
def simple_algorithm(json_file: dict, algorithm_name: str) -> dict: """ Logic layer function for calling correct JSON/XML conversion, running the algorithm through our Python ALT interface and converting the result back to JSON for REST API. :param json_file: `dictionary` containing the input (automaton, grammar or regexp) :param algorithm_name: `string` representing name of the algorithm to be used (see \ :class:`~backend.AlgorithmTypes`) for available algorithm names :return: `dictionary` containing the output of given algorithm (automaton, grammar or regexp) OR `dictionary` with \ exception message and exception type """ try: if algorithm_name == AlgorithmTypes.AUTOMATON_MINIMIZATION: return _automaton_minimization(json_file) elif algorithm_name == AlgorithmTypes.REGEXP_DERIVATION: return _regexp_derivation(json_file) elif algorithm_name == AlgorithmTypes.GRAMMAR_LEFT_RECURSION_REMOVAL: return _grammar_left_recursion(json_file) elif algorithm_name == AlgorithmTypes.GRAMMAR_CNF_CONVERSION: return _grammar_cnf(json_file) elif algorithm_name == AlgorithmTypes.GRAMMAR_CYK: return _grammar_cyk(json_file) else: source = Converter.json_to_xml(json_file, algorithm_name) with AltInterface() as interface: algorithm_result = interface.algorithms(source, algorithm_name) result = Converter.xml_to_json(algorithm_result, algorithm_name) return result except (AltInterfaceException, Converter.JSONDecodeError, Converter.XMLDecodeError) as e: return {'exception': e.msg, 'type': e.exc_type}