Belle II Software development
test_changed_decfiles.py
1
8
9'''
10Simple launcher for decfiles/tests/test_changed_decfiles.py_noexec. This tests whether new decay files work.
11'''
12
13import basf2
14import b2test_utils
15import os
16import subprocess
17
18from git import Repo
19from pathlib import Path
20from tempfile import NamedTemporaryFile
21
22
23def add_hint(errorstring: str):
24
25 hint = "\nDon't forget to add custom (i.e. not yet discovered or measured) particles to " \
26 "decfiles/tests/test_changed_decfiles.pdl, otherwise the test will not pass." \
27 " Already discovered particles should go in framework/particledb/data/evt.pdl instead."
28
29 if 'Unknown particle name' in errorstring:
30 return errorstring + hint
31 else:
32 return errorstring
33
34
35def decfile_uses_generic_dalitz(decfile_path) -> bool:
36 """
37 Decay files using the GENERIC_DALITZ model need an additional XML
38 file specifying the resonances. The XML's path is given in the decfile as a path relative to the working directory. Therefore, in
39 order to test decfiles using GENERIC_DALITZ, basf2 must be run from
40 the directory containing the decfile, otherwise EvtGen will be
41 unable to find the XML. This function returns True if the decfile
42 uses GENERIC_DALITZ.
43 """
44 with open(decfile_path) as decfile:
45 for ln in decfile:
46 if not ln.startswith('#') and 'GENERIC_DALITZ' in ln:
47 return True
48 return False
49
50
51if __name__ == '__main__':
52
54
55 if not b2test_utils.is_ci():
56 b2test_utils.skip_test("Will not test changed decfiles because $BELLE2_IS_CI is not set.")
57
58 if not os.environ.get('BELLE2_LOCAL_DIR'):
59 b2test_utils.skip_test("Test for changed decfiles failed because $BELLE2_LOCAL_DIR is not set.")
60
61 topdir = Path(os.environ['BELLE2_LOCAL_DIR'])
62 assert topdir.is_dir()
63
64 repo = Repo(topdir)
65 merge_base = repo.merge_base('origin/main', repo.head)
66 diff_to_main = repo.head.commit.diff(merge_base)
67
68 added_or_modified_decfiles = [topdir / new_file.a_path for new_file in diff_to_main
69 if (Path(new_file.a_path).suffix == '.dec')
70 and (Path('decfiles/dec') in Path(new_file.a_path).parents)]
71
72 # in case some decfiles are removed, they end up in the list of modified files:
73 # let's keep only the decfiles that are actually found by basf2.find_file
74 added_or_modified_decfiles = [decfile for decfile in added_or_modified_decfiles
75 if basf2.find_file(decfile.as_posix(), silent=True)]
76
77 steering_file = basf2.find_file('decfiles/tests/test_changed_decfiles.py_noexec')
78 custom_evtpdl = basf2.find_file("decfiles/tests/test_changed_decfiles.pdl")
79 default_evtpdl = basf2.find_file('data/framework/particledb/evt.pdl')
80
81 run_results = []
82 if added_or_modified_decfiles:
83 changed_file_string = '\n'.join(str(p) for p in added_or_modified_decfiles)
84 print(f"Changed decayfiles: \n{changed_file_string}")
85
86 with NamedTemporaryFile(mode='w', suffix='.pdl') as tempfile:
87
88 for fname in [custom_evtpdl, default_evtpdl]:
89 with open(fname) as infile:
90 tempfile.write(infile.read())
91
92 for decfile in added_or_modified_decfiles:
93 cwd = decfile.parent if decfile_uses_generic_dalitz(decfile) else None
95 run_results.append(subprocess.run(['basf2', steering_file, str(decfile), tempfile.name],
96 capture_output=True, cwd=cwd))
97
98 files_and_errors = [f'Decfile {added_or_modified_decfiles[i]} failed with output \n'
99 f'{ret.stdout.decode()} \n and error \n {add_hint(ret.stderr.decode())}'
100 for i, ret in enumerate(run_results) if ret.returncode != 0]
101
102 if len(files_and_errors):
103 raise RuntimeError("At least one added decfile has failed.\n"
104 + '\n'.join(files_and_errors))
105
def clean_working_directory()
Definition: __init__.py:194
def configure_logging_for_tests(user_replacements=None)
Definition: __init__.py:106
def skip_test(reason, py_case=None)
Definition: __init__.py:31
bool is_ci()
Definition: __init__.py:421