- # Generate tables:
- # All tests in csv:
- tbl_names = ["{0}-ndr-1t1c-full{1}".format(table["output-file"],
- table["output-file-ext"]),
- "{0}-ndr-2t2c-full{1}".format(table["output-file"],
- table["output-file-ext"]),
- "{0}-ndr-4t4c-full{1}".format(table["output-file"],
- table["output-file-ext"]),
- "{0}-pdr-1t1c-full{1}".format(table["output-file"],
- table["output-file-ext"]),
- "{0}-pdr-2t2c-full{1}".format(table["output-file"],
- table["output-file-ext"]),
- "{0}-pdr-4t4c-full{1}".format(table["output-file"],
- table["output-file-ext"])
- ]
- for file_name in tbl_names:
- with open(file_name, "w") as file_handler:
- file_handler.write(header_str)
- for test in tbl_lst:
- if (file_name.split("-")[-3] in test[0] and # NDR vs PDR
- file_name.split("-")[-2] in test[0]): # cores
- test[0] = "-".join(test[0].split("-")[:-1])
- file_handler.write(",".join([str(item) for item in test]) +
- "\n")
-
- # All tests in txt:
- tbl_names_txt = ["{0}-ndr-1t1c-full.txt".format(table["output-file"]),
- "{0}-ndr-2t2c-full.txt".format(table["output-file"]),
- "{0}-ndr-4t4c-full.txt".format(table["output-file"]),
- "{0}-pdr-1t1c-full.txt".format(table["output-file"]),
- "{0}-pdr-2t2c-full.txt".format(table["output-file"]),
- "{0}-pdr-4t4c-full.txt".format(table["output-file"])
- ]
-
- for i, txt_name in enumerate(tbl_names_txt):
- txt_table = None
- with open(tbl_names[i], 'rb') as csv_file:
+ # Generate csv tables:
+ csv_file = "{0}.csv".format(table["output-file"])
+ with open(csv_file, "w") as file_handler:
+ file_handler.write(header_str)
+ for test in tbl_lst:
+ file_handler.write(",".join([str(item) for item in test]) + "\n")
+
+ convert_csv_to_pretty_txt(csv_file, "{0}.txt".format(table["output-file"]))
+
+
+def table_performance_trending_dashboard(table, input_data):
+ """Generate the table(s) with algorithm:
+ table_performance_trending_dashboard
+ specified in the specification file.
+
+ :param table: Table to generate.
+ :param input_data: Data to process.
+ :type table: pandas.Series
+ :type input_data: InputData
+ """
+
+ logging.info(" Generating the table {0} ...".
+ format(table.get("title", "")))
+
+ # Transform the data
+ logging.info(" Creating the data set for the {0} '{1}'.".
+ format(table.get("type", ""), table.get("title", "")))
+ data = input_data.filter_data(table, continue_on_error=True)
+
+ # Prepare the header of the tables
+ header = ["Test Case",
+ "Trend [Mpps]",
+ "Short-Term Change [%]",
+ "Long-Term Change [%]",
+ "Regressions [#]",
+ "Progressions [#]"
+ ]
+ header_str = ",".join(header) + "\n"
+
+ # Prepare data to the table:
+ tbl_dict = dict()
+ for job, builds in table["data"].items():
+ for build in builds:
+ for tst_name, tst_data in data[job][str(build)].iteritems():
+ if tst_name.lower() in table["ignore-list"]:
+ continue
+ if tbl_dict.get(tst_name, None) is None:
+ groups = re.search(REGEX_NIC, tst_data["parent"])
+ if not groups:
+ continue
+ nic = groups.group(0)
+ tbl_dict[tst_name] = {
+ "name": "{0}-{1}".format(nic, tst_data["name"]),
+ "data": OrderedDict()}
+ try:
+ tbl_dict[tst_name]["data"][str(build)] = \
+ tst_data["result"]["receive-rate"]
+ except (TypeError, KeyError):
+ pass # No data in output.xml for this test
+
+ tbl_lst = list()
+ for tst_name in tbl_dict.keys():
+ data_t = tbl_dict[tst_name]["data"]
+ if len(data_t) < 2:
+ continue
+
+ classification_lst, avgs = classify_anomalies(data_t)
+
+ win_size = min(len(data_t), table["window"])
+ long_win_size = min(len(data_t), table["long-trend-window"])
+
+ try:
+ max_long_avg = max(
+ [x for x in avgs[-long_win_size:-win_size]
+ if not isnan(x)])
+ except ValueError:
+ max_long_avg = nan
+ last_avg = avgs[-1]
+ avg_week_ago = avgs[max(-win_size, -len(avgs))]
+
+ if isnan(last_avg) or isnan(avg_week_ago) or avg_week_ago == 0.0:
+ rel_change_last = nan
+ else:
+ rel_change_last = round(
+ ((last_avg - avg_week_ago) / avg_week_ago) * 100, 2)
+
+ if isnan(max_long_avg) or isnan(last_avg) or max_long_avg == 0.0:
+ rel_change_long = nan
+ else:
+ rel_change_long = round(
+ ((last_avg - max_long_avg) / max_long_avg) * 100, 2)
+
+ if classification_lst:
+ if isnan(rel_change_last) and isnan(rel_change_long):
+ continue
+ tbl_lst.append(
+ [tbl_dict[tst_name]["name"],
+ '-' if isnan(last_avg) else
+ round(last_avg / 1000000, 2),
+ '-' if isnan(rel_change_last) else rel_change_last,
+ '-' if isnan(rel_change_long) else rel_change_long,
+ classification_lst[-win_size:].count("regression"),
+ classification_lst[-win_size:].count("progression")])
+
+ tbl_lst.sort(key=lambda rel: rel[0])
+
+ tbl_sorted = list()
+ for nrr in range(table["window"], -1, -1):
+ tbl_reg = [item for item in tbl_lst if item[4] == nrr]
+ for nrp in range(table["window"], -1, -1):
+ tbl_out = [item for item in tbl_reg if item[5] == nrp]
+ tbl_out.sort(key=lambda rel: rel[2])
+ tbl_sorted.extend(tbl_out)
+
+ file_name = "{0}{1}".format(table["output-file"], table["output-file-ext"])
+
+ logging.info(" Writing file: '{0}'".format(file_name))
+ with open(file_name, "w") as file_handler:
+ file_handler.write(header_str)
+ for test in tbl_sorted:
+ file_handler.write(",".join([str(item) for item in test]) + '\n')
+
+ txt_file_name = "{0}.txt".format(table["output-file"])
+ logging.info(" Writing file: '{0}'".format(txt_file_name))
+ convert_csv_to_pretty_txt(file_name, txt_file_name)
+
+
+def _generate_url(base, testbed, test_name):
+ """Generate URL to a trending plot from the name of the test case.
+
+ :param base: The base part of URL common to all test cases.
+ :param testbed: The testbed used for testing.
+ :param test_name: The name of the test case.
+ :type base: str
+ :type testbed: str
+ :type test_name: str
+ :returns: The URL to the plot with the trending data for the given test
+ case.
+ :rtype str
+ """
+
+ url = base
+ file_name = ""
+ anchor = ".html#"
+ feature = ""
+
+ if "lbdpdk" in test_name or "lbvpp" in test_name:
+ file_name = "link_bonding"
+
+ elif "testpmd" in test_name or "l3fwd" in test_name:
+ file_name = "dpdk"
+
+ elif "memif" in test_name:
+ file_name = "container_memif"
+ feature = "-base"
+
+ elif "srv6" in test_name:
+ file_name = "srv6"
+
+ elif "vhost" in test_name:
+ if "l2xcbase" in test_name or "l2bdbasemaclrn" in test_name:
+ file_name = "vm_vhost_l2"
+ if "l2xcbase" in test_name:
+ feature = "-base-l2xc"
+ elif "l2bdbasemaclrn" in test_name:
+ feature = "-base-l2bd"
+ else:
+ feature = "-base"
+ elif "ip4base" in test_name:
+ file_name = "vm_vhost_ip4"
+ feature = "-base"
+
+ elif "ipsec" in test_name:
+ file_name = "ipsec"
+ feature = "-base-scale"
+
+ elif "ethip4lispip" in test_name or "ethip4vxlan" in test_name:
+ file_name = "ip4_tunnels"
+ feature = "-base"
+
+ elif "ip4base" in test_name or "ip4scale" in test_name:
+ file_name = "ip4"
+ if "xl710" in test_name:
+ feature = "-base-scale-features"
+ elif "iacl" in test_name:
+ feature = "-features-iacl"
+ elif "oacl" in test_name:
+ feature = "-features-oacl"
+ elif "snat" in test_name or "cop" in test_name:
+ feature = "-features"
+ else:
+ feature = "-base-scale"
+
+ elif "ip6base" in test_name or "ip6scale" in test_name:
+ file_name = "ip6"
+ feature = "-base-scale"
+
+ elif "l2xcbase" in test_name or "l2xcscale" in test_name \
+ or "l2bdbasemaclrn" in test_name or "l2bdscale" in test_name \
+ or "l2dbbasemaclrn" in test_name or "l2dbscale" in test_name:
+ file_name = "l2"
+ if "macip" in test_name:
+ feature = "-features-macip"
+ elif "iacl" in test_name:
+ feature = "-features-iacl"
+ elif "oacl" in test_name:
+ feature = "-features-oacl"
+ else:
+ feature = "-base-scale"
+
+ if "x520" in test_name:
+ nic = "x520-"
+ elif "x710" in test_name:
+ nic = "x710-"
+ elif "xl710" in test_name:
+ nic = "xl710-"
+ elif "xxv710" in test_name:
+ nic = "xxv710-"
+ else:
+ nic = ""
+ anchor += nic
+
+ if "64b" in test_name:
+ framesize = "64b"
+ elif "78b" in test_name:
+ framesize = "78b"
+ elif "imix" in test_name:
+ framesize = "imix"
+ elif "9000b" in test_name:
+ framesize = "9000b"
+ elif "1518b" in test_name:
+ framesize = "1518b"
+ elif "114b" in test_name:
+ framesize = "114b"
+ else:
+ framesize = ""
+ anchor += framesize + '-'
+
+ if "1t1c" in test_name:
+ anchor += "1t1c"
+ elif "2t2c" in test_name:
+ anchor += "2t2c"
+ elif "4t4c" in test_name:
+ anchor += "4t4c"
+ elif "2t1c" in test_name:
+ anchor += "2t1c"
+ elif "4t2c" in test_name:
+ anchor += "4t2c"
+ elif "8t4c" in test_name:
+ anchor += "8t4c"
+
+ return url + file_name + '-' + testbed + '-' + nic + framesize + feature + \
+ anchor + feature
+
+
+def table_performance_trending_dashboard_html(table, input_data):
+ """Generate the table(s) with algorithm:
+ table_performance_trending_dashboard_html specified in the specification
+ file.
+
+ :param table: Table to generate.
+ :param input_data: Data to process.
+ :type table: dict
+ :type input_data: InputData
+ """
+
+ testbed = table.get("testbed", None)
+ if testbed is None:
+ logging.error("The testbed is not defined for the table '{0}'.".
+ format(table.get("title", "")))
+ return
+
+ logging.info(" Generating the table {0} ...".
+ format(table.get("title", "")))
+
+ try:
+ with open(table["input-file"], 'rb') as csv_file: