diff --git a/buildtest/builders/base.py b/buildtest/builders/base.py index 20f11203a..f17b875ae 100644 --- a/buildtest/builders/base.py +++ b/buildtest/builders/base.py @@ -932,25 +932,26 @@ def _get_variables(self, variables): return lines - def _extract_content(self, regex): - """Extract content based on the stream and linenum properties - from the regex field and return it as a string. + def _extract_line(self, linenum, content): + """Extract content based on the line number and return it as a string. Args: - regex (dict): regex section from the metrics field + linenum (int): line number + content (str): content to be extracted from """ - stream = regex.get("stream") - content = self._output if stream == "stdout" else self._error - - linenum = regex.get("linenum") - if linenum is not None and content: - lines = content.split("\n") - try: - content = lines[linenum] - except IndexError as e: - content = "" - self.logger.error(e) + if linenum is None: + return content + + lines = content.split("\n") + # removen last line if file ends in new line character + if lines[-1] == "": + lines.pop() + try: + content = lines[linenum] + except IndexError as e: + content = "" + self.logger.error(e) return content def add_metrics(self): @@ -970,7 +971,11 @@ def add_metrics(self): if regex: - content = self._extract_content(regex) + stream = regex.get("stream") + content_input = self._output if stream == "stdout" else self._error + + linenum = regex.get("linenum") + content = self._extract_line(linenum, content_input) if regex.get("re") == "re.match": match = re.match(regex["exp"], content, re.MULTILINE) @@ -998,7 +1003,10 @@ def add_metrics(self): console.print(msg, style="red") continue - content = read_file(resolved_fname) + linenum = file_regex.get("linenum") + content_input = read_file(resolved_fname) + content = self._extract_line(linenum, content_input) + match = ( re.search(file_regex["exp"], content, re.MULTILINE) if content diff --git a/buildtest/schemas/definitions.schema.json b/buildtest/schemas/definitions.schema.json index 7fb6d3932..6d7542043 100644 --- a/buildtest/schemas/definitions.schema.json +++ b/buildtest/schemas/definitions.schema.json @@ -110,6 +110,10 @@ "minimum": 0, "description": "Specify the item number used to index element in `match.group() `_" }, + "linenum": { + "type": "integer", + "description": "Specify the line number used to extract from the file content where regex is applied" + }, "re": { "type": "string", "description": "Specify the regular expression type, it can be either re.search, re.match, or re.fullmatch. By default it uses re.search", diff --git a/tests/builders/metrics_file_regex_with_invalid_linenum.yml b/tests/builders/metrics_file_regex_with_invalid_linenum.yml new file mode 120000 index 000000000..d74dfcdd5 --- /dev/null +++ b/tests/builders/metrics_file_regex_with_invalid_linenum.yml @@ -0,0 +1 @@ +../../tutorials/metrics/metrics_file_regex_with_invalid_linenum.yml \ No newline at end of file diff --git a/tests/builders/metrics_file_regex_with_linenum.yml b/tests/builders/metrics_file_regex_with_linenum.yml new file mode 120000 index 000000000..d9e9c4cd9 --- /dev/null +++ b/tests/builders/metrics_file_regex_with_linenum.yml @@ -0,0 +1 @@ +../../tutorials/metrics/metrics_file_regex_with_linenum.yml \ No newline at end of file diff --git a/tests/builders/test_builders.py b/tests/builders/test_builders.py index 5b1a982d0..70a026de0 100644 --- a/tests/builders/test_builders.py +++ b/tests/builders/test_builders.py @@ -216,3 +216,21 @@ def test_metrics_regex_with_invalid_linenum(): configuration=config, ) cmd.build() + + +def test_metrics_file_regex_with_linenum(): + """This test will perform status check on a particular line from a file where regular expression is applied""" + cmd = BuildTest( + buildspecs=[os.path.join(here, "metrics_file_regex_with_linenum.yml")], + configuration=config, + ) + cmd.build() + + +def test_metrics_file_regex_with_invalid_linenum(): + """This test will test metrics file regex with invalid line number""" + cmd = BuildTest( + buildspecs=[os.path.join(here, "metrics_file_regex_with_invalid_linenum.yml")], + configuration=config, + ) + cmd.build() diff --git a/tutorials/metrics/metrics_file_regex_with_invalid_linenum.yml b/tutorials/metrics/metrics_file_regex_with_invalid_linenum.yml new file mode 100644 index 000000000..cd6646b59 --- /dev/null +++ b/tutorials/metrics/metrics_file_regex_with_invalid_linenum.yml @@ -0,0 +1,16 @@ +buildspecs: + metric_file_regex_with_linenum_failure_example: + executor: generic.local.bash + type: script + description: capture result metric from file path + run: | + echo -e "HPCG result is INVALID with a GFLOP/s rating of=28.1215" > hpcg.txt + echo -e "HPCG result is VALID with a GFLOP/s rating of=68.9888" >> hpcg.txt + tags: tutorials + metrics: + second_line: + type: float + file_regex: + exp: '(\d+\.\d+)$' + linenum: 10 + file: hpcg.txt diff --git a/tutorials/metrics/metrics_file_regex_with_linenum.yml b/tutorials/metrics/metrics_file_regex_with_linenum.yml new file mode 100644 index 000000000..752ac242d --- /dev/null +++ b/tutorials/metrics/metrics_file_regex_with_linenum.yml @@ -0,0 +1,28 @@ +buildspecs: + metric_file_regex_with_linenum_example: + executor: generic.local.bash + type: script + description: capture result metric from file path + run: | + echo -e "HPCG result is INVALID with a GFLOP/s rating of=28.1215" > hpcg.txt + echo -e "HPCG result is VALID with a GFLOP/s rating of=68.9888" >> hpcg.txt + tags: tutorials + metrics: + last_line: + type: float + file_regex: + exp: '(\d+\.\d+)$' + linenum: -1 + file: hpcg.txt + without_linenum: + type: float + file_regex: + exp: '(\d+\.\d+)$' + file: hpcg.txt + status: + assert_eq: + comparisons: + - name: last_line + ref: 68.9888 + - name: without_linenum + ref: 28.1215