def test_malformed_meta_data(): 'Pass a bogus metadata and watch it burn' metadata = [ { 'one': 'two', } ] with pytest.raises(ValueError) as e: process_metadata(metadata) assert 'one' in str(e)
def test_md_atlas_collection_no_element(): 'A collection container that needs an element type' metadata = [ { 'metadata_type': 'add_atlas_event_collection_info', 'name': 'EventInfo', 'include_files': ['xAODEventInfo/EventInfo.h'], 'container_type': 'xAOD::EventInfo', 'contains_collection': True, } ] with pytest.raises(ValueError): process_metadata(metadata)
def test_md_cms_collection_element_type_needed(): 'Make a CMS collection container badly' metadata = [ { 'metadata_type': 'add_cms_event_collection_info', 'name': 'Vertex', 'include_files': ['DataFormats/VertexReco/interface/Vertex.h'], 'container_type': 'reco::VertexCollection', 'contains_collection': True, 'element_pointer': False, } ] with pytest.raises(ValueError): process_metadata(metadata)
def test_bad_meta_data(): 'Pass a bogus metadata and watch it burn' metadata = [ { 'metadata_type': 'add_method_type_info_iiii', 'type_string': 'my_namespace::obj', 'method_name': 'pT', 'return_type': 'int', } ] with pytest.raises(ValueError) as e: process_metadata(metadata) assert 'add_method_type_info_iiii' in str(e)
def test_md_code_block(): 'make sure all options of a code block work' metadata = [ { 'metadata_type': 'inject_code', 'name': "my_code_block", 'body_includes': ['file1.h', 'file2.h'], 'header_includes': ['file3.h', 'file4.h'], 'private_members': ['int first;'], 'instance_initialization': ['first(10)'], 'ctor_lines': ['first = first * 10;'], 'initialize_lines': ['line1', 'line2'], 'link_libraries': ['lib1', 'lib2'], } ] result = process_metadata(metadata) assert len(result) == 1 s = result[0] assert isinstance(s, InjectCodeBlock) assert s.body_includes == ['file1.h', 'file2.h'] assert s.header_includes == ['file3.h', 'file4.h'] assert s.private_members == ['int first;'] assert s.instance_initialization == ['first(10)'] assert s.ctor_lines == ['first = first * 10;'] assert s.link_libraries == ['lib1', 'lib2'] assert s.initialize_lines == ['line1', 'line2']
def test_md_function_call(): 'Inject code to run some C++' metadata = [ { 'metadata_type': 'add_cpp_function', 'name': 'MyDeltaR', 'include_files': ['TVector2.h', 'math.h'], 'arguments': ['eta1', 'phi1', 'eta2', 'phi2'], 'code': [ 'auto d_eta = eta1 - eta2;', 'auto d_phi = TVector2::Phi_mpi_pi(phi1-phi2);', 'auto result = sqrt(d_eta*d_eta + d_phi*d_phi);' ], 'return_type': 'double' } ] specs = process_metadata(metadata) assert len(specs) == 1 spec = specs[0] assert isinstance(spec, CPPCodeSpecification) assert spec.name == 'MyDeltaR' assert spec.include_files == ['TVector2.h', 'math.h'] assert spec.arguments == ['eta1', 'phi1', 'eta2', 'phi2'] assert len(spec.code) == 3 assert spec.result == 'result' assert spec.cpp_return_type == 'double'
def test_md_code_block_empty(): metadata = [ { 'metadata_type': 'inject_code', } ] r = process_metadata(metadata) assert len(r) == 0
def test_md_code_block_bad_item(): metadata = [ { 'metadata_type': 'inject_code', 'body_includes': ['file1.h', 'file2.h'], 'header_includes': ['file3.h', 'file4.h'], 'private_members': ['int first;'], 'instance_initialization': ['first(10)'], 'ctor_lines': ['first = first * 10;'], 'link_libraries_f': ['lib1', 'lib2'], } ] with pytest.raises(ValueError) as e: process_metadata(metadata) assert "link_libraries_f" in str(e)
def test_md_method_type_object_pointer(): 'Make sure a double can be set' metadata = [ { 'metadata_type': 'add_method_type_info', 'type_string': 'my_namespace::obj', 'method_name': 'vertex', 'return_type': 'my_namespace::vertex*', } ] process_metadata(metadata) t = method_type_info('my_namespace::obj', 'vertex') assert t is not None assert t.r_type.type == 'my_namespace::vertex' assert t.r_type.is_a_pointer
def test_md_method_type_double(): 'Make sure a double can be set' metadata = [ { 'metadata_type': 'add_method_type_info', 'type_string': 'my_namespace::obj', 'method_name': 'pT', 'return_type': 'double', } ] process_metadata(metadata) t = method_type_info('my_namespace::obj', 'pT') assert t is not None assert t.r_type.type == 'double' assert not t.r_type.is_a_pointer assert t.deref_depth == 0
def test_md_method_type_collection_ptr(): 'Make sure a double can be set' metadata = [ { 'metadata_type': 'add_method_type_info', 'type_string': 'my_namespace::obj', 'method_name': 'pT', 'return_type_element': 'double', 'return_type_collection': 'vector<double>*', } ] process_metadata(metadata) t = method_type_info('my_namespace::obj', 'pT') assert t is not None assert isinstance(t.r_type, collection) assert t.r_type.is_a_pointer
def test_md_code_block_one_at_a_time(): md = { 'body_includes': ['file1.h', 'file2.h'], 'header_includes': ['file3.h', 'file4.h'], 'private_members': ['int first;'], 'instance_initialization': ['first(10)'], 'ctor_lines': ['first = first * 10;'], 'link_libraries': ['lib1', 'lib2'], } for k in md.keys(): metadata = [ { 'metadata_type': 'inject_code', 'name': "my_code_block", k: md[k], } ] process_metadata(metadata)
def test_md_method_type_custom_collection(): 'Make sure a double can be set' metadata = [ { 'metadata_type': 'add_method_type_info', 'type_string': 'my_namespace::obj', 'method_name': 'pT', 'return_type_element': 'double', 'return_type_collection': 'MyCustomCollection', } ] process_metadata(metadata) t = method_type_info('my_namespace::obj', 'pT') assert t is not None assert isinstance(t.r_type, collection) assert t.r_type.type == 'MyCustomCollection' assert str(t.r_type.element_type) == 'double' assert not t.r_type.is_a_pointer
def test_md_code_block_duplicate_bad(): 'make sure all options of a code block work' block1 = { 'metadata_type': 'inject_code', 'name': "my_code_block", 'body_includes': ['file1.h', 'file2.h'], 'header_includes': ['file3.h', 'file4.h'], 'private_members': ['int first;'], 'instance_initialization': ['first(10)'], 'ctor_lines': ['first = first * 10;'], 'initialize_lines': ['line1', 'line2'], 'link_libraries': ['lib1', 'lib2'], } block2 = dict(block1) block2['body_includes'] = ['file5.h'] metadata = [block1, block2] with pytest.raises(ValueError) as e: process_metadata(metadata) assert 'my_code_block' in str(e)
def test_md_method_type_collection_item_ptr(): 'Make sure a double can be set' metadata = [ { 'metadata_type': 'add_method_type_info', 'type_string': 'my_namespace::obj', 'method_name': 'pT', 'return_type_element': 'double*', } ] process_metadata(metadata) t = method_type_info('my_namespace::obj', 'pT') assert t is not None assert isinstance(t.r_type, collection) assert t.r_type.type == 'std::vector<double*>' assert isinstance(t.r_type.element_type, terminal) assert str(t.r_type.element_type) == 'double*' assert t.r_type.element_type.p_depth == 1 assert not t.r_type.is_a_pointer
def test_md_code_block_duplicate(): 'make sure all options of a code block work' block1 = { 'metadata_type': 'inject_code', 'name': "my_code_block", 'body_includes': ['file1.h', 'file2.h'], 'header_includes': ['file3.h', 'file4.h'], 'private_members': ['int first;'], 'instance_initialization': ['first(10)'], 'ctor_lines': ['first = first * 10;'], 'initialize_lines': ['line1', 'line2'], 'link_libraries': ['lib1', 'lib2'], } metadata = [block1, dict(block1)] r = process_metadata(metadata) assert len(r) == 1
def test_md_add_config_script_dependencies(): 'Check we can properly add some md script' metadata = [ { 'metadata_type': 'add_job_script', 'name': 'script1', 'script': [ 'from AnaAlgorithm.AnaAlgorithmConfig import AnaAlgorithmConfig', "config = AnaAlgorithmConfig( 'CP::SysListLoaderAlg/SysLoaderAlg' )", 'config.sigmaRecommended = 1', 'job.algsAdd( config )', ], 'depends_on': ['name1', 'name2'], } ] specs = process_metadata(metadata) assert len(specs) == 1 spec = specs[0] assert isinstance(spec, JobScriptSpecification) assert spec.depends_on == ['name1', 'name2']
def test_md_atlas_collection_single_obj(): 'A collection container that does not have other things' metadata = [ { 'metadata_type': 'add_atlas_event_collection_info', 'name': 'EventInfo', 'include_files': ['xAODEventInfo/EventInfo.h'], 'container_type': 'xAOD::EventInfo', 'link_libraries': ['xAODEventInfo'], 'contains_collection': False, } ] result = process_metadata(metadata) assert len(result) == 1 s = result[0] assert isinstance(s, EventCollectionSpecification) assert s.backend_name == 'atlas' assert s.name == 'EventInfo' assert s.include_files == ['xAODEventInfo/EventInfo.h'] assert isinstance(s.container_type, atlas_xaod_event_collection_container) assert s.container_type.type == 'xAOD::EventInfo' assert s.libraries == ['xAODEventInfo']
def apply_ast_transformations(self, a: ast.AST): r''' Run through all the transformations that we have on tap to be run on the client side. Return a (possibly) modified ast. ''' # Do tuple resolutions. This might eliminate a whole bunch fo code! a, meta_data = extract_metadata(a) cpp_functions = process_metadata(meta_data) a = change_extension_functions_to_calls(a) a = aggregate_node_transformer().visit(a) a = simplify_chained_calls().visit(a) a = find_known_functions().visit(a) # Any C++ custom code needs to be threaded into the ast method_names = dict(self._method_names) method_names.update({ md.name: (lambda call_node, md=md: cpp_ast.build_CPPCodeValue( md, call_node)) if isinstance(md, cpp_ast.CPPCodeSpecification) # type: ignore else self.build_collection_callback(md) for md in cpp_functions if isinstance(md, (cpp_ast.CPPCodeSpecification, EventCollectionSpecification)) }) a = cpp_ast.cpp_ast_finder(method_names).visit(a) # Save the injection blocks self._inject_blocks = [ md for md in cpp_functions if isinstance(md, InjectCodeBlock) ] # Pull off any joboption blocks for m in cpp_functions: if isinstance(m, JobScriptSpecification): self._job_option_blocks.append(m) # And return the modified ast return a
def test_md_atlas_collection(): 'Make a collection container md' metadata = [ { 'metadata_type': 'add_atlas_event_collection_info', 'name': 'TruthParticles', 'include_files': ['file1.h', 'file2.h'], 'container_type': 'xAOD::ElectronContainer', 'element_type': 'xAOD::Electron', 'contains_collection': True, } ] result = process_metadata(metadata) assert len(result) == 1 s = result[0] assert isinstance(s, EventCollectionSpecification) assert s.backend_name == 'atlas' assert s.name == 'TruthParticles' assert s.include_files == ['file1.h', 'file2.h'] assert isinstance(s.container_type, atlas_xaod_event_collection_collection) assert s.container_type.element_type.type == 'xAOD::Electron' assert s.container_type.type == 'xAOD::ElectronContainer' assert s.libraries == []
def test_md_function_call_renamed_result(): 'Check result name is properly set' metadata = [ { 'metadata_type': 'add_cpp_function', 'name': 'MyDeltaR', 'include_files': ['TVector2.h', 'math.h'], 'arguments': ['eta1', 'phi1', 'eta2', 'phi2'], 'code': [ 'auto d_eta = eta1 - eta2;', 'auto d_phi = TVector2::Phi_mpi_pi(phi1-phi2);', 'auto result_fork = sqrt(d_eta*d_eta + d_phi*d_phi);' ], 'return_type': 'double', 'result_name': 'result_fork' } ] specs = process_metadata(metadata) assert len(specs) == 1 spec = specs[0] assert isinstance(spec, CPPCodeSpecification) assert spec.result == 'result_fork'
def test_md_cms_collection(): 'Make a CMS collection container' metadata = [ { 'metadata_type': 'add_cms_event_collection_info', 'name': 'Vertex', 'include_files': ['DataFormats/VertexReco/interface/Vertex.h'], 'container_type': 'reco::VertexCollection', 'contains_collection': True, 'element_type': 'reco::Vertex', 'element_pointer': False, } ] result = process_metadata(metadata) assert len(result) == 1 s = result[0] assert isinstance(s, EventCollectionSpecification) assert s.backend_name == 'cms' assert s.name == 'Vertex' assert s.include_files == ['DataFormats/VertexReco/interface/Vertex.h'] assert isinstance(s.container_type, cms_aod_event_collection_collection) assert s.container_type.element_type.type == 'reco::Vertex' assert s.container_type.type == 'reco::VertexCollection'
def test_md_method_call(): 'Inject code to run some C++ as a method' metadata = [ { 'metadata_type': 'add_cpp_function', 'name': 'getAttributeFloat', 'include_files': [], 'arguments': ['name'], 'instance_object': 'obj_j', 'method_object': 'xAOD::Jet_v1', 'code': [ 'auto result = obj_j->getAttribute<float>(name);' ], 'return_type': 'double' } ] specs = process_metadata(metadata) assert len(specs) == 1 spec = specs[0] assert isinstance(spec, CPPCodeSpecification) assert spec.method_object == 'xAOD::Jet_v1' assert spec.instance_object == 'obj_j'