diff options
Diffstat (limited to 'resources/libraries/python')
-rw-r--r-- | resources/libraries/python/Constants.py | 61 | ||||
-rw-r--r-- | resources/libraries/python/InterfaceUtil.py | 10 | ||||
-rw-r--r-- | resources/libraries/python/TrafficGenerator.py | 72 | ||||
-rw-r--r-- | resources/libraries/python/autogen/DefaultTestcase.py | 2 | ||||
-rw-r--r-- | resources/libraries/python/autogen/Regenerator.py | 152 | ||||
-rw-r--r-- | resources/libraries/python/autogen/Testcase.py | 10 |
6 files changed, 232 insertions, 75 deletions
diff --git a/resources/libraries/python/Constants.py b/resources/libraries/python/Constants.py index 506b71af69..9822f1c3a0 100644 --- a/resources/libraries/python/Constants.py +++ b/resources/libraries/python/Constants.py @@ -84,3 +84,64 @@ class Constants(object): # Core dump directory CORE_DUMP_DIR = '/tmp' + + # Mapping from NIC name to its bps limit. + # TODO: Implement logic to lower limits to TG NIC or software. Or PCI. + NIC_NAME_TO_LIMIT = { + # TODO: Explain why ~40Gbps NICs are using ~25Gbps limit. + "Cisco-VIC-1227": 10000000000, + "Cisco-VIC-1385": 24500000000, + "Intel-X520-DA2": 10000000000, + "Intel-X553": 10000000000, + "Intel-X710": 10000000000, + "Intel-XL710": 24500000000, + "Intel-XXV710": 24500000000, + } + + # Suite file names use somewhat more rich (less readable) codes for NICs. + NIC_NAME_TO_CODE = { + "Cisco-VIC-1227": "10ge2p1vic1227", + "Cisco-VIC-1385": "40ge2p1vic1385", + "Intel-X520-DA2": "10ge2p1x520", + "Intel-X553": "10ge2p1x553", + "Intel-X710": "10ge2p1x710", + "Intel-XL710": "40ge2p1xl710", + "Intel-XXV710": "25ge2p1xxv710", + } + + # TODO CSIT-1481: Crypto HW should be read from topology file instead. + NIC_NAME_TO_CRYPTO_HW = { + "Intel-X553": "HW_C3xxx", + "Intel-X710": "HW_DH895xcc", + "Intel-XL710": "HW_DH895xcc", + } + + PERF_TYPE_TO_KEYWORD = { + "mrr": "Traffic should pass with maximum rate", + "ndrpdr": "Find NDR and PDR intervals using optimized search", + "soak": "Find critical load using PLRsearch", + } + + PERF_TYPE_TO_SUITE_DOC_VER = { + "mrr" : '''fication:* In MaxReceivedRate tests TG sends traffic\\ +| ... | at line rate and reports total received packets over trial period.\\''', + # TODO: Figure out how to include the full "*[Ver] TG verification:*" + # while keeping this readable and without breaking line length limit. + "ndrpdr": '''fication:* TG finds and reports throughput NDR (Non Drop\\ +| ... | Rate) with zero packet loss tolerance and throughput PDR (Partial Drop\\ +| ... | Rate) with non-zero packet loss tolerance (LT) expressed in percentage\\ +| ... | of packets transmitted. NDR and PDR are discovered for different\\ +| ... | Ethernet L2 frame sizes using MLRsearch library.\\''', + "soak": '''fication:* TG sends traffic at dynamically computed\\ +| ... | rate as PLRsearch algorithm gathers data and improves its estimate\\ +| ... | of a rate at which a prescribed small fraction of packets\\ +| ... | would be lost. After set time, the serarch stops\\ +| ... | and the algorithm reports its current estimate.\\''', + } + + PERF_TYPE_TO_TEMPLATE_DOC_VER = { + "mrr": '''Measure MaxReceivedRate for ${frame_size}B frames\\ +| | ... | using burst trials throughput test.\\''', + "ndrpdr": '''Measure NDR and PDR values using MLRsearch algorithm.\\''', + "soak": '''Estimate critical rate using PLRsearch algorithm.\\''', + } diff --git a/resources/libraries/python/InterfaceUtil.py b/resources/libraries/python/InterfaceUtil.py index a1a9b739e0..df45e39560 100644 --- a/resources/libraries/python/InterfaceUtil.py +++ b/resources/libraries/python/InterfaceUtil.py @@ -1325,18 +1325,20 @@ class InterfaceUtil(object): exec_cmd_no_error(node, cmd, sudo=True) @staticmethod - def init_avf_interface(node, ifc_key, numvfs=1, topology_type='L2'): + def init_avf_interface(node, ifc_key, numvfs=1, traffic_type='L2'): """Init PCI device by creating VFs and bind them to vfio-pci for AVF driver testing on DUT. :param node: DUT node. :param ifc_key: Interface key from topology file. :param numvfs: Number of VFs to initialize, 0 - disable the VFs. - :param topology_type: Topology type. + :param traffic_type: Expected type of traffic, affects spoofing. + Default value "L2" sets linux interface spoof off. + Other values do not do that. :type node: dict :type ifc_key: str :type numvfs: int - :type topology_type: str + :type traffic_type: str :returns: Virtual Function topology interface keys. :rtype: list """ @@ -1375,7 +1377,7 @@ class InterfaceUtil(object): format(pci=pf_pci_addr) InterfaceUtil.set_linux_interface_trust_on(node, pf_dev, vf_id=vf_id) - if topology_type == 'L2': + if traffic_type == 'L2': InterfaceUtil.set_linux_interface_spoof_off(node, pf_dev, vf_id=vf_id) InterfaceUtil.set_linux_interface_mac(node, pf_dev, vf_mac_addr, diff --git a/resources/libraries/python/TrafficGenerator.py b/resources/libraries/python/TrafficGenerator.py index ea587d7558..5f92888fe8 100644 --- a/resources/libraries/python/TrafficGenerator.py +++ b/resources/libraries/python/TrafficGenerator.py @@ -37,21 +37,21 @@ class TGDropRateSearchImpl(DropRateSearch): super(TGDropRateSearchImpl, self).__init__() def measure_loss(self, rate, frame_size, loss_acceptance, - loss_acceptance_type, traffic_type, skip_warmup=False): + loss_acceptance_type, traffic_profile, skip_warmup=False): """Runs the traffic and evaluate the measured results. :param rate: Offered traffic load. :param frame_size: Size of frame. :param loss_acceptance: Permitted drop ratio or frames count. :param loss_acceptance_type: Type of permitted loss. - :param traffic_type: Module name as a traffic type identifier. + :param traffic_profile: Module name as a traffic profile identifier. See resources/traffic_profiles/trex for implemented modules. :param skip_warmup: Start TRex without warmup traffic if true. :type rate: float :type frame_size: str :type loss_acceptance: float :type loss_acceptance_type: LossAcceptanceType - :type traffic_type: str + :type traffic_profile: str :type skip_warmup: bool :returns: Drop threshold exceeded? (True/False) :rtype: bool @@ -70,12 +70,12 @@ class TGDropRateSearchImpl(DropRateSearch): if skip_warmup: tg_instance.trex_stl_start_remote_exec(self.get_duration(), unit_rate, frame_size, - traffic_type, + traffic_profile, warmup_time=0.0) else: tg_instance.trex_stl_start_remote_exec(self.get_duration(), unit_rate, frame_size, - traffic_type) + traffic_profile) loss = tg_instance.get_loss() sent = tg_instance.get_sent() if self.loss_acceptance_type_is_percentage(): @@ -124,7 +124,7 @@ class TrafficGenerator(AbstractMeasurer): self._ifaces_reordered = False # Parameters not given by measure(). self.frame_size = None - self.traffic_type = None + self.traffic_profile = None self.warmup_time = None @property @@ -388,15 +388,15 @@ class TrafficGenerator(AbstractMeasurer): raise RuntimeError('TRex stateless runtime error') def trex_stl_start_remote_exec( - self, duration, rate, framesize, traffic_type, async_call=False, + self, duration, rate, frame_size, traffic_profile, async_call=False, latency=True, warmup_time=5.0, unidirection=False, tx_port=0, rx_port=1): """Execute script on remote node over ssh to start traffic. :param duration: Time expresed in seconds for how long to send traffic. :param rate: Traffic rate expressed with units (pps, %) - :param framesize: L2 frame size to send (without padding and IPG). - :param traffic_type: Module name as a traffic type identifier. + :param frame_size: L2 frame size to send (without padding and IPG). + :param traffic_profile: Module name as a traffic profile identifier. See resources/traffic_profiles/trex for implemented modules. :param async_call: If enabled then don't wait for all incomming trafic. :param latency: With latency measurement. @@ -408,8 +408,8 @@ class TrafficGenerator(AbstractMeasurer): Default: 1 :type duration: float :type rate: str - :type framesize: str - :type traffic_type: str + :type frame_size: str + :type traffic_profile: str :type async_call: bool :type latency: bool :type warmup_time: float @@ -425,11 +425,12 @@ class TrafficGenerator(AbstractMeasurer): command = ( "sh -c '{tool}/resources/tools/trex/trex_stateless_profile.py" " --profile {prof}/resources/traffic_profiles/trex/{traffic}.py" - " --duration {duration} --frame_size {framesize} --rate {rate}" + " --duration {duration} --frame_size {frame_size} --rate {rate}" " --warmup_time {warmup} --port_0 {p_0} --port_1 {p_1}").format( tool=Constants.REMOTE_FW_DIR, prof=Constants.REMOTE_FW_DIR, - traffic=traffic_type, duration=duration, framesize=framesize, - rate=rate, warmup=warmup_time, p_0=p_0, p_1=p_1) + traffic=traffic_profile, duration=duration, + frame_size=frame_size, rate=rate, warmup=warmup_time, p_0=p_0, + p_1=p_1) if async_call: command += " --async" if latency: @@ -473,7 +474,7 @@ class TrafficGenerator(AbstractMeasurer): self.trex_stl_stop_remote_exec(self._node) def send_traffic_on_tg( - self, duration, rate, framesize, traffic_type, warmup_time=5, + self, duration, rate, frame_size, traffic_profile, warmup_time=5, async_call=False, latency=True, unidirection=False, tx_port=0, rx_port=1): """Send traffic from all configured interfaces on TG. @@ -489,12 +490,13 @@ class TrafficGenerator(AbstractMeasurer): TODO: Is it better to have less descriptive argument names just to make them less probable to be viewed as misleading or confusing? - See https://gerrit.fd.io/r/#/c/17625/11/resources/libraries/python/TrafficGenerator.py@406 + See https://gerrit.fd.io/r/#/c/17625/11/resources/libraries/python\ + /TrafficGenerator.py@406 :param duration: Duration of test traffic generation in seconds. :param rate: Offered load per interface (e.g. 1%, 3gbps, 4mpps, ...). - :param framesize: Frame size (L2) in Bytes. - :param traffic_type: Module name as a traffic type identifier. + :param frame_size: Frame size (L2) in Bytes. + :param traffic_profile: Module name as a traffic profile identifier. See resources/traffic_profiles/trex for implemented modules. :param warmup_time: Warmup phase in seconds. :param async_call: Async mode. @@ -506,8 +508,8 @@ class TrafficGenerator(AbstractMeasurer): Default: 1 :type duration: str :type rate: str - :type framesize: str - :type traffic_type: str + :type frame_size: str + :type traffic_profile: str :type warmup_time: float :type async_call: bool :type latency: bool @@ -532,8 +534,8 @@ class TrafficGenerator(AbstractMeasurer): raise RuntimeError('TG subtype not defined') elif node['subtype'] == NodeSubTypeTG.TREX: self.trex_stl_start_remote_exec( - duration, rate, framesize, traffic_type, async_call, latency, - warmup_time, unidirection, tx_port, rx_port) + duration, rate, frame_size, traffic_profile, async_call, + latency, warmup_time, unidirection, tx_port, rx_port) else: raise NotImplementedError("TG subtype not supported") @@ -586,20 +588,20 @@ class TrafficGenerator(AbstractMeasurer): raise Exception("Traffic loss {} above loss acceptance: {}".format( loss, loss_acceptance)) - def set_rate_provider_defaults(self, frame_size, traffic_type, + def set_rate_provider_defaults(self, frame_size, traffic_profile, warmup_time=0.0): """Store values accessed by measure(). :param frame_size: Frame size identifier or value [B]. - :param traffic_type: Module name as a traffic type identifier. + :param traffic_profile: Module name as a traffic profile identifier. See resources/traffic_profiles/trex for implemented modules. :param warmup_time: Traffic duration before measurement starts [s]. :type frame_size: str or int - :type traffic_type: str + :type traffic_profile: str :type warmup_time: float """ self.frame_size = frame_size - self.traffic_type = str(traffic_type) + self.traffic_profile = str(traffic_profile) self.warmup_time = float(warmup_time) def measure(self, duration, transmit_rate): @@ -620,7 +622,7 @@ class TrafficGenerator(AbstractMeasurer): # Trex needs target Tr per stream, but reports aggregate Tx and Dx. unit_rate = str(transmit_rate / 2.0) + "pps" self.send_traffic_on_tg( - duration, unit_rate, self.frame_size, self.traffic_type, + duration, unit_rate, self.frame_size, self.traffic_profile, warmup_time=self.warmup_time, latency=True) transmit_count = int(self.get_sent()) loss_count = int(self.get_loss()) @@ -635,7 +637,7 @@ class OptimizedSearch(object): @staticmethod def perform_optimized_ndrpdr_search( - frame_size, traffic_type, minimum_transmit_rate, + frame_size, traffic_profile, minimum_transmit_rate, maximum_transmit_rate, packet_loss_ratio=0.005, final_relative_width=0.005, final_trial_duration=30.0, initial_trial_duration=1.0, number_of_intermediate_phases=2, @@ -643,7 +645,7 @@ class OptimizedSearch(object): """Setup initialized TG, perform optimized search, return intervals. :param frame_size: Frame size identifier or value [B]. - :param traffic_type: Module name as a traffic type identifier. + :param traffic_profile: Module name as a traffic profile identifier. See resources/traffic_profiles/trex for implemented modules. :param minimum_transmit_rate: Minimal bidirectional target transmit rate [pps]. @@ -663,7 +665,7 @@ class OptimizedSearch(object): Default 1 is suitable for fairly stable tests, less stable tests might get better overal duration with 2 or more. :type frame_size: str or int - :type traffic_type: str + :type traffic_profile: str :type minimum_transmit_rate: float :type maximum_transmit_rate: float :type packet_loss_ratio: float @@ -682,7 +684,7 @@ class OptimizedSearch(object): # to be able to use trex_stl-*() tg_instance = BuiltIn().get_library_instance( 'resources.libraries.python.TrafficGenerator') - tg_instance.set_rate_provider_defaults(frame_size, traffic_type) + tg_instance.set_rate_provider_defaults(frame_size, traffic_profile) algorithm = MultipleLossRatioSearch( measurer=tg_instance, final_trial_duration=final_trial_duration, final_relative_width=final_relative_width, @@ -695,13 +697,13 @@ class OptimizedSearch(object): @staticmethod def perform_soak_search( - frame_size, traffic_type, minimum_transmit_rate, + frame_size, traffic_profile, minimum_transmit_rate, maximum_transmit_rate, plr_target=1e-7, tdpt=0.2, initial_count=50, timeout=1800.0): """Setup initialized TG, perform soak search, return avg and stdev. :param frame_size: Frame size identifier or value [B]. - :param traffic_type: Module name as a traffic type identifier. + :param traffic_profile: Module name as a traffic profile identifier. See resources/traffic_profiles/trex for implemented modules. :param minimum_transmit_rate: Minimal bidirectional target transmit rate [pps]. @@ -717,7 +719,7 @@ class OptimizedSearch(object): takes significant time even without any trial results. :param timeout: The search will stop after this overall time [s]. :type frame_size: str or int - :type traffic_type: str + :type traffic_profile: str :type minimum_transmit_rate: float :type maximum_transmit_rate: float :type plr_target: float @@ -728,7 +730,7 @@ class OptimizedSearch(object): """ tg_instance = BuiltIn().get_library_instance( 'resources.libraries.python.TrafficGenerator') - tg_instance.set_rate_provider_defaults(frame_size, traffic_type) + tg_instance.set_rate_provider_defaults(frame_size, traffic_profile) algorithm = PLRsearch( measurer=tg_instance, trial_duration_per_trial=tdpt, packet_loss_ratio_target=plr_target, diff --git a/resources/libraries/python/autogen/DefaultTestcase.py b/resources/libraries/python/autogen/DefaultTestcase.py index 0aaf40d7ca..5db81a80d4 100644 --- a/resources/libraries/python/autogen/DefaultTestcase.py +++ b/resources/libraries/python/autogen/DefaultTestcase.py @@ -30,6 +30,6 @@ class DefaultTestcase(Testcase): template_string = r''' | ${tc_num}-${frame_str}-${cores_str}c-''' + suite_id + r''' | | [Tags] | ${frame_str} | ${cores_str}C -| | framesize=${frame_num} | phy_cores=${cores_num} +| | frame_size=${frame_num} | phy_cores=${cores_num} ''' super(DefaultTestcase, self).__init__(template_string) diff --git a/resources/libraries/python/autogen/Regenerator.py b/resources/libraries/python/autogen/Regenerator.py index bae0e4f9fe..f47c88b022 100644 --- a/resources/libraries/python/autogen/Regenerator.py +++ b/resources/libraries/python/autogen/Regenerator.py @@ -20,6 +20,7 @@ from os import getcwd import sys from .DefaultTestcase import DefaultTestcase +from resources.libraries.python.Constants import Constants # Copied from https://stackoverflow.com/a/14981125 @@ -63,18 +64,18 @@ class Regenerator(object): When None, default list is used. List item is a dict, argument names are keys. The initialized testcase_class should accept those, and "num". - DefaultTestcase accepts "framesize" and "phy_cores". + DefaultTestcase accepts "frame_size" and "phy_cores". :type pattern: str :type is_ip6: boolean :type tc_kwargs_list: list of tuple or None """ - protocol_to_min_framesize = { + protocol_to_min_frame_size = { "ip4": 64, "ip6": 78, "vxlan+ip4": 114 # What is the real minimum for latency stream? } - min_framesize_values = protocol_to_min_framesize.values() + min_frame_size_values = protocol_to_min_frame_size.values() def get_iface_and_suite_id(filename): """Get interface and suite ID. @@ -110,7 +111,7 @@ class Regenerator(object): """ # TODO: Is there a better way to disable some combinations? emit = True - if kwargs["framesize"] == 9000: + if kwargs["frame_size"] == 9000: if "vic1227" in iface: # Not supported in HW. emit = False @@ -127,7 +128,7 @@ class Regenerator(object): # Soak test take too long, do not risk other than tc01. if kwargs["phy_cores"] != 1: emit = False - if kwargs["framesize"] not in min_framesize_values: + if kwargs["frame_size"] not in min_frame_size_values: emit = False if emit: file_out.write(testcase.generate(num=num, **kwargs)) @@ -151,37 +152,128 @@ class Regenerator(object): """ num = 1 for tc_kwargs in tc_kwargs_list: - num = add_testcase(testcase, iface, suite_id, file_out, num, - **tc_kwargs) + num = add_testcase( + testcase, iface, suite_id, file_out, num, **tc_kwargs) + + def replace_defensively( + whole, to_replace, replace_with, how_many, msg, in_filename): + """Replace substrings while checking the number of occurences. + + Return edited copy of the text (so original string is not affected). + + :param whole: The text to perform replacements on. + :param to_replace: Substring occurences of which to replace. + :param replace_with: Substring to replace occurences with. + :param how_many: Number of occurences to expect. + :param msg: Error message to raise. + :param in_filename: File name in which the error occured. + :type whole: str + :type to_replace: str + :type replace_with: str + :type how_many: int + :type msg: str + :type in_filename: str + :return: The whole text after replacements are done. + :rtype: str + :raise ValueError: If number of occurences does not match. + """ + found = whole.count(to_replace) + if found != how_many: + raise ValueError(in_filename + ": " + msg) + return whole.replace(to_replace, replace_with) + + def write_files(in_filename, in_prolog, kwargs_list): + """Using given filename and prolog, write all generated suites. + + :param in_filename: Template filename to derive real filenames from. + :param in_prolog: Template content to derive real content from. + :param kwargs_list: List of kwargs for add_testcase. + :type in_filename: str + :type in_prolog: str + :type kwargs_list: list of dict + """ + for suite_type in Constants.PERF_TYPE_TO_KEYWORD.keys(): + tmp_filename = replace_defensively( + in_filename, "ndrpdr", suite_type, 1, + "File name should contain suite type once.", in_filename) + tmp_prolog = replace_defensively( + in_prolog, "ndrpdr".upper(), suite_type.upper(), 1, + "Suite type should appear once in uppercase (as tag).", + in_filename) + tmp_prolog = replace_defensively( + tmp_prolog, + "Find NDR and PDR intervals using optimized search", + Constants.PERF_TYPE_TO_KEYWORD[suite_type], 1, + "Main search keyword should appear once in suite.", + in_filename) + tmp_prolog = replace_defensively( + tmp_prolog, + Constants.PERF_TYPE_TO_SUITE_DOC_VER["ndrpdr"], + Constants.PERF_TYPE_TO_SUITE_DOC_VER[suite_type], + 1, "Exact suite type doc not found.", in_filename) + tmp_prolog = replace_defensively( + tmp_prolog, + Constants.PERF_TYPE_TO_TEMPLATE_DOC_VER["ndrpdr"], + Constants.PERF_TYPE_TO_TEMPLATE_DOC_VER[suite_type], + 1, "Exact template type doc not found.", in_filename) + _, suite_id = get_iface_and_suite_id(tmp_filename) + testcase = self.testcase_class(suite_id) + for nic_name in Constants.NIC_NAME_TO_CODE.keys(): + out_filename = replace_defensively( + tmp_filename, "10ge2p1x710", + Constants.NIC_NAME_TO_CODE[nic_name], 1, + "File name should contain NIC code once.", in_filename) + out_prolog = replace_defensively( + tmp_prolog, "Intel-X710", nic_name, 2, + "NIC name should appear twice (tag and variable).", + in_filename) + if out_prolog.count("HW_") == 2: + # TODO CSIT-1481: Crypto HW should be read + # from topology file instead. + if nic_name in Constants.NIC_NAME_TO_CRYPTO_HW.keys(): + out_prolog = replace_defensively( + out_prolog, "HW_DH895xcc", + Constants.NIC_NAME_TO_CRYPTO_HW[nic_name], 1, + "HW crypto name should appear.", in_filename) + iface, suite_id = get_iface_and_suite_id(out_filename) + with open(out_filename, "w") as file_out: + file_out.write(out_prolog) + add_testcases( + testcase, iface, suite_id, file_out, kwargs_list) if not self.quiet: eprint("Regenerator starts at {cwd}".format(cwd=getcwd())) - min_framesize = protocol_to_min_framesize[protocol] + min_frame_size = protocol_to_min_frame_size[protocol] kwargs_list = tc_kwargs_list if tc_kwargs_list else [ - {"framesize": min_framesize, "phy_cores": 1}, - {"framesize": min_framesize, "phy_cores": 2}, - {"framesize": min_framesize, "phy_cores": 4}, - {"framesize": 1518, "phy_cores": 1}, - {"framesize": 1518, "phy_cores": 2}, - {"framesize": 1518, "phy_cores": 4}, - {"framesize": 9000, "phy_cores": 1}, - {"framesize": 9000, "phy_cores": 2}, - {"framesize": 9000, "phy_cores": 4}, - {"framesize": "IMIX_v4_1", "phy_cores": 1}, - {"framesize": "IMIX_v4_1", "phy_cores": 2}, - {"framesize": "IMIX_v4_1", "phy_cores": 4} + {"frame_size": min_frame_size, "phy_cores": 1}, + {"frame_size": min_frame_size, "phy_cores": 2}, + {"frame_size": min_frame_size, "phy_cores": 4}, + {"frame_size": 1518, "phy_cores": 1}, + {"frame_size": 1518, "phy_cores": 2}, + {"frame_size": 1518, "phy_cores": 4}, + {"frame_size": 9000, "phy_cores": 1}, + {"frame_size": 9000, "phy_cores": 2}, + {"frame_size": 9000, "phy_cores": 4}, + {"frame_size": "IMIX_v4_1", "phy_cores": 1}, + {"frame_size": "IMIX_v4_1", "phy_cores": 2}, + {"frame_size": "IMIX_v4_1", "phy_cores": 4} ] - for filename in glob(pattern): + for in_filename in glob(pattern): if not self.quiet: - eprint("Regenerating filename:", filename) - with open(filename, "r") as file_in: - text = file_in.read() - text_prolog = "".join(text.partition("*** Test Cases ***")[:-1]) - iface, suite_id = get_iface_and_suite_id(filename) - testcase = self.testcase_class(suite_id) - with open(filename, "w") as file_out: - file_out.write(text_prolog) - add_testcases(testcase, iface, suite_id, file_out, kwargs_list) + eprint("Regenerating in_filename:", in_filename) + if not in_filename.endswith("ndrpdr.robot"): + eprint("Error in {fil}: non-primary suite type encountered." + .format(fil=in_filename)) + sys.exit(1) + iface, _ = get_iface_and_suite_id(in_filename) + if not iface.endswith("10ge2p1x710"): + eprint("Error in {fil}: non-primary NIC encountered." + .format(fil=in_filename)) + sys.exit(1) + with open(in_filename, "r") as file_in: + in_prolog = "".join( + file_in.read().partition("*** Test Cases ***")[:-1]) + write_files(in_filename, in_prolog, kwargs_list) if not self.quiet: eprint("Regenerator ends.") eprint() # To make autogen check output more readable. diff --git a/resources/libraries/python/autogen/Testcase.py b/resources/libraries/python/autogen/Testcase.py index dd58547f33..7d0a29b0ad 100644 --- a/resources/libraries/python/autogen/Testcase.py +++ b/resources/libraries/python/autogen/Testcase.py @@ -34,29 +34,29 @@ class Testcase(object): """ self.template = Template(template_string) - def generate(self, num, framesize, phy_cores): + def generate(self, num, frame_size, phy_cores): """Return string of test case code with placeholders filled. Fail if there are placeholders left unfilled. :param num: Test case number. Example value: 4. - :param framesize: Imix string or numeric frame size. Example: 74. + :param frame_size: Imix string or numeric frame size. Example: 74. :param phy_cores: Number of physical cores to use. Example: 2. :type num: int - :type framesize: str or int + :type frame_size: str or int :type phy_cores: int or str :returns: Filled template, usable as test case code. :rtype: str """ try: - fsize = int(framesize) + fsize = int(frame_size) subst_dict = { "frame_num": "${%d}" % fsize, "frame_str": "%dB" % fsize } except ValueError: # Assuming an IMIX string. subst_dict = { - "frame_num": str(framesize), + "frame_num": str(frame_size), "frame_str": "IMIX" } cores_str = str(phy_cores) |