19 """Find matching control token in string.
23 openchar (str): opening char e.g '{'
24 closechar (str): closing char e.g '}'
27 int: position of matching closing char in string.
30 if string[0] == openchar:
32 while end < len(string)
and count > 0:
33 if string[end] == openchar:
35 elif string[end] == closechar:
43 Determine metavariable types from source code and assert correctness
49 "softwareTriggerResult":
"double",
51 "softwareTriggerResultNonPrescaled":
"double",
52 "isDaughterOfList":
"bool",
53 "isGrandDaughterOfList":
"bool",
54 "daughterDiffOf":
"double",
55 "daughterDiffOfPhi":
"double",
56 "daughterDiffOfClusterPhi":
"double",
57 "mcDaughterDiffOfPhi":
"double",
58 "grandDaughterDiffOfPhi":
"double",
59 "grandDaughterDiffOfClusterPhi":
"double",
60 "daughterDiffOfPhiCMS":
"double",
61 "daughterDiffOfClusterPhiCMS":
"double",
66 registering_regex = re.compile(
67 r"(?s)REGISTER_METAVARIABLE.*?Manager::VariableDataType::(?:c_double|c_int|c_bool)"
70 extract_regex = re.compile(
71 r'REGISTER_METAVARIABLE\(".*?",(?P<function_name>[^,]*),.*?Manager::VariableDataType::c_(?P<enumtype>double|bool|int)'
74 lambda_type_regex = re.compile(
r"-> (?P<lambdatype>double|bool|int)")
77 """Check all metavariable types for specified file.
80 filepath (str): path to file containing REGISTER_METAVARIABLE
83 AssertionError: Raised if no expected function definition is found.
84 AssertionError: Rased if lambda function has no associated
85 type information, or no lambda function is defined.
88 int: number of metavariables in file.
89 Used for sanity checks of the coverage.
93 with open(filepath)
as fp:
94 filecontent = fp.read()
97 registering_statements = self.
registering_regexregistering_regex.findall(filecontent)
100 registering_statements = list(
102 lambda line: line.replace(
" ",
"").replace(
"\n",
""),
103 registering_statements,
107 for statement
in registering_statements:
109 match_content = self.
extract_regexextract_regex.match(statement)
110 function_name = match_content.groupdict()[
"function_name"]
111 enumtype = match_content.groupdict()[
"enumtype"]
113 if function_name
in self.
hardcodedhardcoded:
117 f
"Metavariable '{function_name}' in file {filepath}:\n"
118 f
"Metavariable function return type and Manager::VariableDataType have to match.\n"
119 f
"Expected: Manager::VariableDataType::{self.hardcoded[function_name]}, actual: Manager::VariableDataType::{enumtype}",
124 function_definition_regex = re.compile(
125 r"Manager::FunctionPtr %s\(.*\)[^\{]*" % function_name
128 regular_definition_regex = re.compile(
129 r"(?P<return_type>double|int|bool) %s\(.*?\)" % function_name
133 definition = function_definition_regex.search(filecontent)
134 if definition
is not None:
135 func_body_start = definition.end()
139 regular_definition_regex.search(filecontent)
143 if return_type
is not None:
147 f
"Metavariable '{function_name}' in file {filepath}:\n"
148 "Metavariable function return type and Manager::VariableDataType have to match."
149 f
"Return type is {return_type} but it is registered as Manager::VariableDataType::c_{enumtype}.\n",
153 raise AssertionError(
154 f
"Metavariable '{function_name}' in file {filepath}:\n"
155 "Metavariable function return type and Manager::VariableDataType have to match."
156 "Return type of function could not be automatically determined from the source code."
157 "You can add an exception by adding the expected return type information to "
158 "the 'hardcoded' dictionary of this testcase."
163 filecontent[func_body_start:],
"{",
"}"
166 func_body = filecontent[func_body_start:func_body_end]
170 if lambdatype_match
is not None:
171 lambdatype = lambdatype_match.groupdict()[
"lambdatype"]
175 f
"Metavariable '{function_name}' in file {filepath}:\n"
176 f
"Lambda function has return type {lambdatype} "
177 f
"but is registered with Manager::VariableDataType::c_{enumtype}.\n"
178 "VariableDataType and lambda return type have to match.",
181 raise AssertionError(
182 f
"Metavariable '{function_name}' in {filepath}:\n"
183 "VariableDataType and lambda definition have to match.\n"
184 "Either lambda function is missing return type information"
185 ", or lambda definition could not be found.\n"
186 "Please add return type annotation '(const Particle * particle) -> double/int/bool' to lambda.\n"
187 "Or add this metavariable as exception, by adding the expected return type information in the 'hardcoded' dictionary of this testcase\n"
192 return len(registering_statements)
195 """Metavariables have to be registered with the correct Manager::Variable::VariableDataType enum value. This test makes sure Metavariable definition and variable registration are correct."""
198 subprocess.run([
"grep",
"-V"], check=
True, capture_output=
True)
199 except subprocess.CalledProcessError:
200 logging.basicConfig(format=
"%(message)s")
202 "TEST SKIPPED: MetavariableDataTypeTest skipped because grep is not available."
207 analysis_module = basf2.find_file(
"analysis")
208 files = subprocess.run(
211 "REGISTER_METAVARIABLE",
220 files = files.stdout.decode().split(
"\n")
221 files = list(
filter(
lambda file: file.endswith(
".cc"), files))
223 num_files = len(files)
224 print(f
"Number of files including meta-variables is {num_files}")
227 self.assertGreaterEqual(num_files, 13)
229 num_metavariables = 0
230 for filepath
in files:
231 num_metavariables += self.
process_fileprocess_file(filepath)
234 print(f
"Number of meta-variables is {num_metavariables}")
235 self.assertGreaterEqual(num_metavariables, 229)
238 if __name__ ==
"__main__":
unsigned long int findMatchedParenthesis(std::string str, char open='[', char close=']')
Returns position of the matched closing parenthesis if the first character in the given string contai...
std::map< ExpRun, std::pair< double, double > > filter(const std::map< ExpRun, std::pair< double, double >> &runs, double cut, std::map< ExpRun, std::pair< double, double >> &runsRemoved)
filter events to remove runs shorter than cut, it stores removed runs in runsRemoved