def test_upwards_relocation_with_one_level_must_return_expected_result( basic_trees, basic_types): root, new_root = basic_trees new_element = entities.Element(name='Employee', element_type=basic_types['token_type']) # New element was moved from network upwards new_root.add_child(new_element) root.get_child_by_name('Network').add_child(new_element) recalculate_hashes(new_root) recalculate_hashes(root) # Now, they must be different assert root != new_root result = compare(root, new_root) expected_relocations = [('/Root/Network/Employee', '/Root/Employee')] expected_removals = ['/Root/Network/Employee'] assert result['relocations'] == expected_relocations assert result['removals'] == expected_removals others_empty(result, 'relocations', 'removals')
def test_rename_and_sub_tree_changes_must_return_expected_renames( basic_trees, basic_types): root, new_root = basic_trees # Renaming Network to another name assert new_root.children[0].name == 'Network' new_root.children[0].name = 'NewNetwork' # Inside network, lets change Owner to Person assert new_root.children[0].children[0].name == 'Owner' new_root.children[0].children[0].name = 'Person' recalculate_hashes(new_root) recalculate_hashes(root) # Now, they must be different assert root != new_root result = compare(root, new_root) expected_renames = [ ('/Root/Network', '/Root/NewNetwork'), ('/Root/Network/Owner', '/Root/Network/Person'), ] # As we are using sets, we need to sort our result to compare it. result['renames'].sort(key=lambda x: x[0]) assert result['renames'] == expected_renames others_empty(result, 'renames')
def test_relocation_with_one_level_must_return_expected_result( basic_trees, basic_types): root, new_root = basic_trees service = new_root.children[3] # Moving Root->Service to Root->Network->Service new_root.children[0].add_child(service) new_root.remove_child(service) recalculate_hashes(new_root) recalculate_hashes(root) # Now, they must be different assert root != new_root result = compare(root, new_root) expected_relocations = [('/Root/Service', '/Root/Network/Service')] expected_removals = ['/Root/Service'] assert result['relocations'] == expected_relocations assert result['removals'] == expected_removals others_empty(result, 'relocations', 'removals')
def test_rename_in_two_different_levels_must_return_expected_operation( basic_trees): root, new_root = basic_trees # Let's remove Root->Network->Person new_root.children[0].children[0].name = 'Person' # Change name of Root->ReadOnly new_root.children[2].name = 'DisableChanges' recalculate_hashes(new_root) recalculate_hashes(root) # Now, they must be different assert root != new_root result = compare(root, new_root) expected_renames = [ ('/Root/Network/Owner', '/Root/Network/Person'), ('/Root/ReadOnly', '/Root/DisableChanges'), ] # As we are using sets, we need to sort our result to compare it. result['renames'].sort(key=lambda x: x[0]) assert result['renames'] == expected_renames others_empty(result, 'renames')
def test_rename_with_similiar_name_must_return_expected_association( basic_trees, basic_types): root, new_root = basic_trees # Renaming other fields new_root.children[1].name = 'NewOwner' new_root.children[3].name = 'ServiceNew' # Two new fields with same type but different names to be used in renames root_name = entities.Element(name='Name', element_type=basic_types['token_type']) root_foo = entities.Element(name='Foo', element_type=basic_types['token_type']) root_operation = entities.Element(name='Operation', element_type=basic_types['token_type']) new_root_name = entities.Element(name='NewName', element_type=basic_types['token_type']) new_root_foo = entities.Element(name='Bar', element_type=basic_types['token_type']) new_root_operation = entities.Element( name='OperationNew', element_type=basic_types['token_type']) root.add_child(root_name) root.add_child(root_foo) root.add_child(root_operation) new_root.add_child(new_root_name) new_root.add_child(new_root_foo) new_root.add_child(new_root_operation) recalculate_hashes(new_root) recalculate_hashes(root) # Now, they must be different assert root != new_root result = compare(root, new_root) expected_renames = [ ('/Root/Foo', '/Root/Bar'), ('/Root/Name', '/Root/NewName'), ('/Root/Operation', '/Root/OperationNew'), ('/Root/Owner', '/Root/NewOwner'), ('/Root/Service', '/Root/ServiceNew'), ] # As we are using sets, we need to sort our result to compare it. result['renames'].sort(key=lambda x: x[0]) assert result['renames'] == expected_renames others_empty(result, 'renames')
def test_reorder_with_only_order_changes(basic_trees, basic_types): root, new_root = basic_trees network = new_root.get_child_by_name('Network') network.element_type.children = list(reversed(network.children)) recalculate_hashes(new_root) recalculate_hashes(root) result = compare(root, new_root) expected_reorder = ['/Root/Network'] assert result['reorders'] == expected_reorder others_empty(result, 'reorders')
def test_imediate_circular_dependency_rename_must_return_expected_result( basic_trees, basic_types): root, new_root = basic_trees # Circular dependency of network just inside network root_network = root.get_child_by_name('Network') root_network.add_child(root_network) # Add a new module node inside network of our ORIGINAL tree root_module_type = entities.ElementType( name='ModuleType', children=[ entities.Element(name='Owner', element_type=basic_types['token_type']), ]) root_network.add_child( entities.Element(name='Module', element_type=root_module_type)) # Add a new module node inside network of our NEW tree module_type = entities.ElementType( name='ModuleType', children=[ entities.Element(name='Name', element_type=basic_types['token_type']), ]) network = new_root.get_child_by_name('Network') # Adding a circular dependency network.add_child(network) network.add_child(entities.Element(name='Module', element_type=module_type)) recalculate_hashes(new_root) recalculate_hashes(root) result = compare(root, new_root) expected_renames = [('/Root/Network/Module/Owner', '/Root/Network/Module/Name')] assert result['renames'] == expected_renames others_empty(result, 'renames')
def test_additions_in_two_levels_must_return_expected_operation( basic_trees, basic_types): root, new_root = basic_trees enabled = entities.Element(name='Enabled', element_type=basic_types['boolean_type']) new_root.children[0].add_child(enabled) recalculate_hashes(new_root) recalculate_hashes(root) # Now, they must be different assert root != new_root result = compare(root, new_root) expected_additions = ['/Root/Network/Enabled'] assert result['additions'] == expected_additions others_empty(result, 'additions')
def test_rename_with_two_levels_must_return_expected_operation(basic_trees): root, new_root = basic_trees # Let's remove Root->Network->Person new_root.children[0].children[0].name = 'Person' recalculate_hashes(new_root) recalculate_hashes(root) # Now, they must be different assert root != new_root result = compare(root, new_root) expected_renames = [ ('/Root/Network/Owner', '/Root/Network/Person'), ] assert result['renames'] == expected_renames others_empty(result, 'renames')
def test_rename_with_one_level_must_return_expected_operation(basic_trees): root, new_root = basic_trees # Change name of network node to Net new_root.children[0].name = 'Net' recalculate_hashes(new_root) recalculate_hashes(root) # Now, they must be different assert root != new_root result = compare(root, new_root) expected_renames = [ ('/Root/Network', '/Root/Net'), ] assert result['renames'] == expected_renames others_empty(result, 'renames')
def test_relocation_with_new_sub_element_must_return_expected_result( basic_trees, basic_types): root, new_root = basic_trees # Moving Root->Service to new node Root->Module->Service service = new_root.children[3] new_root.remove_child(service) module_children = [ entities.Element(name='Owner', element_type=basic_types['token_type']), service ] module_type = entities.ElementType(name='ModuleType', children=module_children) module = entities.Element(name='Module', element_type=module_type) new_root.add_child(module) recalculate_hashes(new_root) recalculate_hashes(root) # Now, they must be different assert root != new_root result = compare(root, new_root) expected_relocations = [('/Root/Service', '/Root/Module/Service')] expected_additions = ['/Root/Module'] expected_removals = ['/Root/Service'] assert result['relocations'] == expected_relocations assert result['additions'] == expected_additions assert result['removals'] == expected_removals others_empty(result, 'relocations', 'additions', 'removals')
def test_removal_with_one_level(basic_trees): root, new_root = basic_trees # Let's remove RootType->Owner children = new_root.element_type.children del children[1] new_root.element_type.children = children recalculate_hashes(new_root) recalculate_hashes(root) # Now, they must be different assert root != new_root result = compare(root, new_root) expected_removals = [ '/Root/Owner', ] assert result['removals'] == expected_removals others_empty(result, 'removals')
def test_removal_two_levels(basic_trees): root, new_root = basic_trees # Let's remove RootType->Network->Owner network = new_root.get_child_by_name('Network') del network.children[0] network.element_type.children = network.children recalculate_hashes(new_root) recalculate_hashes(root) # Now, they must be different assert root != new_root result = compare(root, new_root) expected_removals = [ '/Root/Network/Owner', ] assert result['removals'] == expected_removals others_empty(result, 'removals')
def test_circular_dependency_rename_tag_must_return_expected_result( basic_trees, basic_types): root, new_root = basic_trees network = new_root.children[0] # Rename Root->Network->ReadOnly attr network.children[1].name = 'OnlyRead' module_children = [ entities.Element(name='Owner', element_type=basic_types['token_type']), network # Adding a ciclic dependency here ] module_type = entities.ElementType(name='ModuleType', children=module_children) module = entities.Element(name='Module', element_type=module_type) network.add_child(module) recalculate_hashes(new_root) recalculate_hashes(root) expected_renames = [ ('/Root/Network/ReadOnly', '/Root/Network/OnlyRead'), ] expected_additions = [ '/Root/Network/Module', ] result = compare(root, new_root) assert result['renames'] == expected_renames assert result['additions'] == expected_additions others_empty(result, 'renames', 'additions')
def get_xslt(): if not request.is_json: return jsonify({ 'error': 'Bad Request, json expected', 'xslt': '' }), 400 data = request.get_json() if 'srcSchema' not in data: return jsonify({ 'error': 'Bad Request, "srcSchema" expected', 'xslt': '' }), 400 if 'dstSchema' not in data: return jsonify({ 'error': 'Bad Request, "dstSchema" expected', 'xslt': '' }), 400 if 'documents' not in data['srcSchema']: return jsonify({ 'error': 'Bad Request, "srcSchema/documents" expected', 'xslt': '' }), 400 if 'documents' not in data['dstSchema']: return jsonify({ 'error': 'Bad Request, "dstSchema/documents" expected', 'xslt': '' }), 400 if len(data['srcSchema']['documents']) == 0: return jsonify({ 'error': 'Bad Request, expected at least one document', 'xslt': '' }), 400 if len(data['dstSchema']['documents']) == 0: return jsonify({ 'error': 'Bad Request, expected at least one document', 'xslt': '' }), 400 repo_src = _build_repository(data['srcSchema']['documents']) repo_dst = _build_repository(data['dstSchema']['documents']) src_result = repo_src.get_main_element() dst_result = repo_dst.get_main_element() if not src_result: return jsonify({ 'error': 'Bad Request, expected at least one document as primary in "srcSchema"', 'xslt': '' }), 400 if not dst_result: return jsonify({ 'error': 'Bad Request, expected at least one document as primary in "dstSchema"', 'xslt': '' }), 400 src_element = src_result['element'] dst_element = dst_result['element'] recalculate_hashes(src_element) recalculate_hashes(dst_element) compare_result = compare(src_element, dst_element) xslt = generate_xslt(src_element, dst_element, compare_result, src_result['namespaces'], dst_result['location']) # TODO old_field_count = None new_field_count = None unchanged_count = None typerenamed_count = None graph_similar = None add_graph_similar = None similar_doc = None # TODO (handle nodes in additions and removals) removed_count = len(compare_result['removals']) added_count = len(compare_result['additions']) relocations = len(compare_result['relocations']) reorders = len(compare_result['reorders']) renamed_count = len(compare_result['renames']) return jsonify({ 'xslt': xslt, 'translationMetrics': { 'oldFieldCount': old_field_count, 'newFieldCount': new_field_count, 'removedFields': removed_count, 'addedFields': added_count, 'reorders': reorders, 'renamedFields': renamed_count, 'relocatedFields': relocations, 'renamedTypes': typerenamed_count, 'percentMapped': None # TODO } })