-# Copyright (c) 2019 Cisco and/or its affiliates.
+# Copyright (c) 2020 Cisco and/or its affiliates.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
r'PDR_LOWER:\s(\d+.\d+).*\n.*\n'
r'PDR_UPPER:\s(\d+.\d+)'
)
+ REGEX_NDRPDR_GBPS = re.compile(
+ r'NDR_LOWER:.*,\s(\d+.\d+).*\n.*\n'
+ r'NDR_UPPER:.*,\s(\d+.\d+).*\n'
+ r'PDR_LOWER:.*,\s(\d+.\d+).*\n.*\n'
+ r'PDR_UPPER:.*,\s(\d+.\d+)'
+ )
REGEX_PERF_MSG_INFO = re.compile(
r'NDR_LOWER:\s(\d+.\d+)\s.*\s(\d+.\d+)\s.*\n.*\n.*\n'
r'PDR_LOWER:\s(\d+.\d+)\s.*\s(\d+.\d+)\s.*\n.*\n.*\n'
"""
if msg.message.count(u"return STDOUT Version:") or \
- msg.message.count(u"VPP Version:") or \
- msg.message.count(u"VPP version:"):
+ msg.message.count(u"VPP Version:") or \
+ msg.message.count(u"VPP version:"):
self._version = str(re.search(self.REGEX_VERSION_VPP, msg.message).
group(2))
self._data[u"metadata"][u"version"] = self._version
return throughput, status
+ def _get_ndrpdr_throughput_gbps(self, msg):
+ """Get NDR_LOWER, NDR_UPPER, PDR_LOWER and PDR_UPPER in Gbps from the
+ test message.
+
+ :param msg: The test message to be parsed.
+ :type msg: str
+ :returns: Parsed data as a dict and the status (PASS/FAIL).
+ :rtype: tuple(dict, str)
+ """
+
+ gbps = {
+ u"NDR": {u"LOWER": -1.0, u"UPPER": -1.0},
+ u"PDR": {u"LOWER": -1.0, u"UPPER": -1.0}
+ }
+ status = u"FAIL"
+ groups = re.search(self.REGEX_NDRPDR_GBPS, msg)
+
+ if groups is not None:
+ try:
+ gbps[u"NDR"][u"LOWER"] = float(groups.group(1))
+ gbps[u"NDR"][u"UPPER"] = float(groups.group(2))
+ gbps[u"PDR"][u"LOWER"] = float(groups.group(3))
+ gbps[u"PDR"][u"UPPER"] = float(groups.group(4))
+ status = u"PASS"
+ except (IndexError, ValueError):
+ pass
+
+ return gbps, status
+
def _get_plr_throughput(self, msg):
"""Get PLRsearch lower bound and PLRsearch upper bound from the test
message.
name = test.name.lower()
# Remove TC number from the TC long name (backward compatibility):
- self._test_id = re.sub(self.REGEX_TC_NUMBER, u"", longname)
+ self._test_id = re.sub(
+ self.REGEX_TC_NUMBER, u"", longname.replace(u"snat", u"nat")
+ )
# Remove TC number from the TC name (not needed):
- test_result[u"name"] = re.sub(self.REGEX_TC_NUMBER, "", name)
+ test_result[u"name"] = re.sub(
+ self.REGEX_TC_NUMBER, "", name.replace(u"snat", u"nat")
+ )
- test_result[u"parent"] = test.parent.name.lower()
+ test_result[u"parent"] = test.parent.name.lower().\
+ replace(u"snat", u"nat")
test_result[u"tags"] = tags
test_result["doc"] = test.doc.\
replace(u'"', u"'").\
return
if test.status == u"PASS":
- if u"NDRPDR" in tags:
+ if u"DEVICETEST" in tags:
+ test_result[u"type"] = u"DEVICETEST"
+ elif u"NDRPDR" in tags:
test_result[u"type"] = u"NDRPDR"
test_result[u"throughput"], test_result[u"status"] = \
self._get_ndrpdr_throughput(test.message)
+ test_result[u"gbps"], test_result[u"status"] = \
+ self._get_ndrpdr_throughput_gbps(test.message)
test_result[u"latency"], test_result[u"status"] = \
self._get_ndrpdr_latency(test.message)
elif u"SOAK" in tags:
groups = re.search(self.REGEX_BMRR, test.message)
if groups is not None:
items_str = groups.group(1)
- items_float = [float(item.strip()) for item
- in items_str.split(",")]
+ items_float = [
+ float(item.strip()) for item in items_str.split(",")
+ ]
# Use whole list in CSIT-1180.
stats = jumpavg.AvgStdevStats.for_runs(items_float)
test_result[u"result"][u"receive-rate"] = stats.avg
}
except (AttributeError, IndexError, ValueError, TypeError):
test_result[u"status"] = u"FAIL"
- elif u"DEVICETEST" in tags:
- test_result[u"type"] = u"DEVICETEST"
else:
test_result[u"status"] = u"FAIL"
self._data[u"tests"][self._test_id] = test_result
:returns: Nothing.
"""
if test_kw.name.count(u"Show Runtime On All Duts") or \
- test_kw.name.count(u"Show Runtime Counters On All Duts"):
+ test_kw.name.count(u"Show Runtime Counters On All Duts") or \
+ test_kw.name.count(u"Vpp Show Runtime On All Duts"):
self._msg_type = u"test-show-runtime"
self._sh_run_counter += 1
- elif test_kw.name.count(u"Install Dpdk Test On All Duts") and \
- not self._version:
- self._msg_type = u"dpdk-version"
else:
return
test_kw.messages.visit(self)
if setup_kw.name.count(u"Show Vpp Version On All Duts") \
and not self._version:
self._msg_type = u"vpp-version"
+ elif setup_kw.name.count(u"Install Dpdk Framework On All Duts") and \
+ not self._version:
+ self._msg_type = u"dpdk-version"
elif setup_kw.name.count(u"Set Global Variable") \
and not self._timestamp:
self._msg_type = u"timestamp"
"""
return self.data[job][build][u"tests"]
- def _parse_tests(self, job, build, log):
+ def _parse_tests(self, job, build):
"""Process data from robot output.xml file and return JSON structured
data.
:param job: The name of job which build output data will be processed.
:param build: The build which output data will be processed.
- :param log: List of log messages.
:type job: str
:type build: dict
- :type log: list of tuples (severity, msg)
:returns: JSON data structure.
:rtype: dict
"""
try:
result = ExecutionResult(data_file)
except errors.DataError as err:
- log.append(
- (u"ERROR", f"Error occurred while parsing output.xml: "
- f"{repr(err)}")
+ logging.error(
+ f"Error occurred while parsing output.xml: {repr(err)}"
)
return None
checker = ExecutionChecker(metadata, self._cfg.mapping,
:type repeat: int
"""
- logs = list()
-
- logs.append(
- (u"INFO", f" Processing the job/build: {job}: {build[u'build']}")
- )
+ logging.info(f" Processing the job/build: {job}: {build[u'build']}")
state = u"failed"
success = False
data = None
do_repeat = repeat
while do_repeat:
- success = download_and_unzip_data_file(self._cfg, job, build, pid,
- logs)
+ success = download_and_unzip_data_file(self._cfg, job, build, pid)
if success:
break
do_repeat -= 1
if not success:
- logs.append(
- (u"ERROR",
- f"It is not possible to download the input data file from the "
- f"job {job}, build {build[u'build']}, or it is damaged. "
- f"Skipped.")
+ logging.error(
+ f"It is not possible to download the input data file from the "
+ f"job {job}, build {build[u'build']}, or it is damaged. "
+ f"Skipped."
)
if success:
- logs.append(
- (u"INFO",
- f" Processing data from the build {build[u'build']} ...")
- )
- data = self._parse_tests(job, build, logs)
+ logging.info(f" Processing data from build {build[u'build']}")
+ data = self._parse_tests(job, build)
if data is None:
- logs.append(
- (u"ERROR",
- f"Input data file from the job {job}, build "
- f"{build[u'build']} is damaged. Skipped.")
+ logging.error(
+ f"Input data file from the job {job}, build "
+ f"{build[u'build']} is damaged. Skipped."
)
else:
state = u"processed"
try:
remove(build[u"file-name"])
except OSError as err:
- logs.append(
- ("ERROR", f"Cannot remove the file {build[u'file-name']}: "
- f"{repr(err)}")
+ logging.error(
+ f"Cannot remove the file {build[u'file-name']}: {repr(err)}"
)
# If the time-period is defined in the specification file, remove all
# files which are outside the time period.
+ is_last = False
timeperiod = self._cfg.input.get(u"time-period", None)
if timeperiod and data:
now = dt.utcnow()
# Remove the data and the file:
state = u"removed"
data = None
- logs.append(
- (u"INFO",
- f" The build {job}/{build[u'build']} is "
- f"outdated, will be removed.")
+ is_last = True
+ logging.info(
+ f" The build {job}/{build[u'build']} is "
+ f"outdated, will be removed."
)
- logs.append((u"INFO", u" Done."))
-
- for level, line in logs:
- if level == u"INFO":
- logging.info(line)
- elif level == u"ERROR":
- logging.error(line)
- elif level == u"DEBUG":
- logging.debug(line)
- elif level == u"CRITICAL":
- logging.critical(line)
- elif level == u"WARNING":
- logging.warning(line)
-
- return {u"data": data, u"state": state, u"job": job, u"build": build}
+ logging.info(u" Done.")
+
+ return {
+ u"data": data,
+ u"state": state,
+ u"job": job,
+ u"build": build,
+ u"last": is_last
+ }
def download_and_parse_data(self, repeat=1):
"""Download the input data files, parse input data from input files and
for build in builds:
result = self._download_and_parse_build(job, build, repeat)
+ if result[u"last"]:
+ break
build_nr = result[u"build"][u"build"]
if result[u"data"]:
if not isfile(local_file):
raise PresentationError(f"The file {local_file} does not exist.")
+ try:
+ build_nr = int(local_file.split(u"/")[-1].split(u".")[0])
+ except (IndexError, ValueError):
+ pass
+
build = {
u"build": build_nr,
u"status": u"failed",
self._cfg.add_build(job, build)
logging.info(f"Processing {job}: {build_nr:2d}: {local_file}")
- data = self._parse_tests(job, build, list())
+ data = self._parse_tests(job, build)
if data is None:
raise PresentationError(
f"Error occurred while parsing the file {local_file}"
data[job][str(build)][
test_id][param] = u"No Data"
except KeyError as err:
- logging.error(repr(err))
if continue_on_error:
+ logging.debug(repr(err))
continue
+ logging.error(repr(err))
return None
return data