From 64a9e3a2c1ab0cd2e699754ca5e876518041a49e Mon Sep 17 00:00:00 2001 From: Narayana-CT Date: Thu, 20 Aug 2026 17:06:11 +0530 Subject: [PATCH 01/13] lf_interop_port_reset_test.py: clarify naming in main(), __init__() and change_port_to_ip() Signed-off-by: Narayana-CT --- py-scripts/lf_interop_port_reset_test.py | 194 +++++++++++------------ 1 file changed, 93 insertions(+), 101 deletions(-) diff --git a/py-scripts/lf_interop_port_reset_test.py b/py-scripts/lf_interop_port_reset_test.py index 51f8dc3f0..351830bc4 100755 --- a/py-scripts/lf_interop_port_reset_test.py +++ b/py-scripts/lf_interop_port_reset_test.py @@ -85,13 +85,12 @@ def __init__(self, host, dut=None, ssid=None, passwd=None, - encryp=None, - reset=None, + encryption=None, + reset_count=None, mgr_ip=None, - time_int=None, - wait_time=None, + reset_interval_sec=None, device_list=None, - suporrted_release=None, + supported_release=None, forget_network=True, dowebgui=False, result_dir=None, @@ -107,8 +106,8 @@ def __init__(self, host, super().__init__(lfclient_host=host, lfclient_port=8080) self.total_connects = [] - self.total_ass_rejects = [] - self.total_ass_attemst = [] + self.total_assoc_rejections = [] + self.total_assoc_attempts = [] self.total_scans = [] self.total_disconnects = [] self.total_resets = [] @@ -125,14 +124,14 @@ def __init__(self, host, self.encrypt_value = 0 self.host = host self.port = port - self.phn_name = [] + self.android_serials = [] self.dut_name = dut self.ssid = ssid self.passwd = passwd - self.encryp = encryp + self.encryption = encryption self.mgr_ip = mgr_ip - self.reset = reset - self.time_int = time_int + self.reset_count = reset_count + self.reset_interval_sec = reset_interval_sec self.device_list = device_list self.forget_network = forget_network self.result_dir = result_dir @@ -154,16 +153,15 @@ def __init__(self, host, self.rotation_list = rotation.split(',') self.current_coordinate = None self.current_angle = None - # self.wait_time = wait_time - self.supported_release = suporrted_release - self.device_name = [] + self.supported_release = supported_release + self.android_user_names = [] self.lf_report = lf_report_pdf.lf_report(_path="" if not self.dowebgui else self.result_dir, _results_dir_name="Interop_port_reset_test", _output_html="port_reset_test.html", _output_pdf="port_reset_test.pdf") self.report_path = self.lf_report.get_report_path() self.base_interop_profile = base.RealDevice(manager_ip=self.host, server_ip=self.mgr_ip, ssid_5g=self.ssid, - encryption_5g=self.encryp, passwd_5g=self.passwd, disconnect_devices=self.forget_network, reboot=False, selected_bands=["5g"]) + encryption_5g=self.encryption, passwd_5g=self.passwd, disconnect_devices=self.forget_network, reboot=False, selected_bands=["5g"]) self.utility = base.UtilityInteropWifi(host_ip=self.host) # logging.basicConfig(filename='port_reset.log', filemode='w', format='%(asctime)s - %(message)s', @@ -195,9 +193,8 @@ def change_port_to_ip(self, upstream_port): # proceed without a resolved manager IP, so retry for a while and then # abort instead of silently continuing with an unresolved port name. if upstream_port.count('.') != 3: - target_port_list = self.name_to_eid(upstream_port) - shelf, resource, port, _ = target_port_list - response = self.json_get_with_retry(f'/port/{shelf}/{resource}/{port}?fields=ip') + shelf, resource, port_name, _ = self.name_to_eid(upstream_port) + response = self.json_get_with_retry(f'/port/{shelf}/{resource}/{port_name}?fields=ip') try: upstream_port = response['interface']['ip'] except (TypeError, KeyError) as e: @@ -238,7 +235,7 @@ def selecting_devices_from_available(self): port=self.port, ssid=self.ssid, passwd=self.passwd, - encryption=self.encryp, + encryption=self.encryption, release=self.supported_release, screen_size_prcnt=0.4, _debug_on=False, @@ -706,7 +703,7 @@ def generate_coordinate_csv(self, reset_dict, r): def performing_resets(self, test_start_time=None): reset_list = [] - for i in range(self.reset): + for i in range(self.reset_count): reset_list.append(i) logging.info(f"Given No.of iterations for Reset : {len(reset_list)}") logging.info("Reset list:" + str(reset_list)) @@ -715,7 +712,7 @@ def performing_resets(self, test_start_time=None): interval = 300 test_stopped_by_user = False charge_check = time.time() + interval - for r, _ in zip(range(self.reset), reset_dict): + for r, _ in zip(range(self.reset_count), reset_dict): if self.robot_test: current_time = time.time() if current_time >= charge_check: @@ -740,8 +737,8 @@ def performing_resets(self, test_start_time=None): test_stopped_by_user = True break charge_check = current_time + interval - logging.info(f"Waiting until given {self.time_int} sec time intervel to finish...") - time.sleep(int(self.time_int)) # sleeping until time interval finish + logging.info(f"Waiting until given {self.reset_interval_sec} sec time intervel to finish...") + time.sleep(int(self.reset_interval_sec)) # sleeping until time interval finish logging.info(f"Iteration :- {r}") logging.info("Reset -" + str(r)) local_dict = dict.fromkeys(self.adb_device_list) @@ -821,7 +818,7 @@ def performing_resets(self, test_start_time=None): 'cx time (us)': 0 } keys_to_delete = [] - for i in range(self.reset): + for i in range(self.reset_count): if reset_dict.get(i) is None: keys_to_delete.append(i) else: @@ -891,8 +888,8 @@ def run(self): raise RuntimeError("There is no active devices please check system.") else: for i in range(len(self.adb_device_list)): - self.phn_name.append(self.adb_device_list[i].split(".")[2]) - logging.info(f"Separated device names from the full name: {self.phn_name}") + self.android_serials.append(self.adb_device_list[i].split(".")[2]) + logging.info(f"Separated device names from the full name: {self.android_serials}") # check status of devices phantom = [] @@ -900,8 +897,8 @@ def run(self): phantom.append(self.interop.get_device_details(device=i, query="phantom")) if self.adb_device_list or self.windows_list or self.linux_list or self.mac_list: for i in self.adb_device_list: - self.device_name.append(self.interop.get_device_details(device=i, query="user-name")) - logging.info(f"ADB user-names for selected devices: {self.device_name}") + self.android_user_names.append(self.interop.get_device_details(device=i, query="user-name")) + logging.info(f"ADB user-names for selected devices: {self.android_user_names}") logging.info("Checking heath data...") health = dict.fromkeys(self.adb_device_list) logging.info(f"Initial Health Data For Android Clients: {health}") @@ -1003,7 +1000,7 @@ def generate_overall_graph(self, reset_dict=None, figsize=(13, 5), _alignmen=Non _legend_fontsize=None, text_font=12, bar_text_rotation=45, graph_suffix=""): dict_ = ['Port Resets', 'Disconnected', 'Scans', 'Assoc Attempts', "Association Rejection", 'Connected'] data = dict.fromkeys(dict_) - data['Port Resets'] = self.reset * len(self.all_selected_devices) + data['Port Resets'] = self.reset_count * len(self.all_selected_devices) conected_list, laptop_conected_list = [], [] disconnected_list, laptop_disconnected_list = [], [] @@ -1162,7 +1159,7 @@ def per_client_graph(self, data=None, name=None, figsize=(13, 5), _alignmen=None def generate_overall_graph_table(self, reset_dict, device_list): if self.robot_test: - self.total_resets, self.total_disconnects, self.total_scans, self.total_ass_attemst, self.total_ass_rejects, self.total_connects = [], [], [], [], [], [] + self.total_resets, self.total_disconnects, self.total_scans, self.total_assoc_attempts, self.total_assoc_rejections, self.total_connects = [], [], [], [], [], [] for y, _ in zip(device_list, range(len(device_list))): reset_count_ = list(reset_dict.keys()) reset_count = [] @@ -1182,7 +1179,7 @@ def generate_overall_graph_table(self, reset_dict, device_list): dict_ = ['Port Resets', 'Disconnects', 'Scans', 'Association Attempts', "Association Rejections", 'Connects'] data = dict.fromkeys(dict_) - data['Port Resets'] = self.reset + data['Port Resets'] = self.reset_count dis = 0 for i in disconnected: @@ -1212,16 +1209,16 @@ def generate_overall_graph_table(self, reset_dict, device_list): # print(f"Final data for per client graph for {y}: {data}") # fetching the total dissconnects, connects, ass_attemsts, ass_rejections, scans - self.total_resets.append(self.reset) + self.total_resets.append(self.reset_count) self.total_disconnects.append(sum(disconnected)) self.total_scans.append(sum(scanning)) - self.total_ass_attemst.append(sum(asso_attempts)) - self.total_ass_rejects.append(sum(assorej)) + self.total_assoc_attempts.append(sum(asso_attempts)) + self.total_assoc_rejections.append(sum(assorej)) self.total_connects.append(sum(connected)) def individual_client_info(self, reset_dict, device_list): # per client table and graphs - # self.total_resets, self.total_disconnects, self.total_scans, self.total_ass_attemst, self.total_ass_rejects, self.total_connects = [], [], [], [], [], [] + # self.total_resets, self.total_disconnects, self.total_scans, self.total_assoc_attempts, self.total_assoc_rejections, self.total_connects = [], [], [], [], [], [] for y, z in zip(device_list, range(len(device_list))): reset_count_ = list(reset_dict.keys()) reset_count = [] @@ -1242,7 +1239,7 @@ def individual_client_info(self, reset_dict, device_list): dict_ = ['Port Resets', 'Disconnects', 'Scans', 'Association Attempts', "Association Rejections", 'Connects'] data = dict.fromkeys(dict_) - data['Port Resets'] = self.reset + data['Port Resets'] = self.reset_count dis = 0 for i in disconnected: @@ -1320,11 +1317,11 @@ def generate_report(self, reset_dict=None, test_dur=None): date = str(datetime.now()).split(",")[0].replace(" ", "-").split(".")[0] security = "" - if self.encryp == "psk2": + if self.encryption == "psk2": security = "wpa2" - elif self.encryp == "psk3": + elif self.encryption == "psk3": security = "wpa3" - elif self.encryp == "psk": + elif self.encryption == "psk": security = "wpa" else: security = "open" @@ -1333,10 +1330,10 @@ def generate_report(self, reset_dict=None, test_dur=None): "LANforge ip": self.host, "SSID": self.ssid, "Security": security, - "Total Reset Count": self.reset, + "Total Reset Count": self.reset_count, "No of Clients": f"{len(self.all_selected_devices)} (Windows: {len(self.windows_list)}, Linux: {len(self.linux_list)}, Mac: {len(self.mac_list)}, Android: {len(self.adb_device_list)})", # noqa: E501 # "Wait Time": str(self.wait_time) + " sec", - "Time intervel between resets": str(self.time_int) + " sec", + "Time intervel between resets": str(self.reset_interval_sec) + " sec", "Test Duration": test_dur, } self.lf_report.set_title("Port Reset Test") @@ -1368,7 +1365,7 @@ def generate_report(self, reset_dict=None, test_dur=None): "4. Association Attempts: Total number of association attempts (Associating state) made by all clients after WiFi is re-enabled in the full test.
" "4. Association Rejections: Total number of association rejections made by all clients after WiFi is re-enabled in the full test.
" "6. Connected: Total number of successful connections (Associated state) achieved by all clients during the test when WiFi is re-enabled.
" - # " Here real clients used is "+ str(self.clients) + "and number of resets provided is " + str(self.reset) + # " Here real clients used is "+ str(self.clients) + "and number of resets provided is " + str(self.reset_count) ) self.lf_report.build_objective() graph1 = self.generate_overall_graph(reset_dict=reset_dict, figsize=(13, 5), _alignmen=None, bar_width=0.5, @@ -1415,8 +1412,8 @@ def generate_report(self, reset_dict=None, test_dur=None): "Port Resets": self.total_resets, "Disconnects": self.total_disconnects, "Scans": self.total_scans, - "Assoc Attemts": self.total_ass_attemst, - "Assoc Rejects": self.total_ass_rejects, + "Assoc Attemts": self.total_assoc_attempts, + "Assoc Rejects": self.total_assoc_rejections, "Connects": self.total_connects } test_setup = pd.DataFrame(table_2) @@ -1465,11 +1462,11 @@ def generate_report_for_robo(self): date = str(datetime.now()).split(",")[0].replace(" ", "-").split(".")[0] # self.lf_report.move_data(_file_name="overall_reset_test.log") security = "" - if self.encryp == "psk2": + if self.encryption == "psk2": security = "wpa2" - elif self.encryp == "psk3": + elif self.encryption == "psk3": security = "wpa3" - elif self.encryp == "psk": + elif self.encryption == "psk": security = "wpa" else: security = "open" @@ -1478,10 +1475,10 @@ def generate_report_for_robo(self): "LANforge ip": self.host, "SSID": self.ssid, "Security": security, - "Total Reset Count": self.reset, + "Total Reset Count": self.reset_count, "No of Clients": f"{len(self.all_selected_devices)} (Windows: {len(self.windows_list)}, Linux: {len(self.linux_list)}, Mac: {len(self.mac_list)}, Android: {len(self.adb_device_list)})", # noqa: E501 # "Wait Time": str(self.wait_time) + " sec", - "Time intervel between resets": str(self.time_int) + " sec", + "Time intervel between resets": str(self.reset_interval_sec) + " sec", } test_setup_info["Selected Coordinates"] = self.coordinate if self.rotation_enabled: @@ -1518,7 +1515,7 @@ def generate_report_for_robo(self): "4. Association Attempts: Total number of association attempts (Associating state) made by all clients after WiFi is re-enabled in the full test.
" "4. Association Rejections: Total number of association rejections made by all clients after WiFi is re-enabled in the full test.
" "6. Connected: Total number of successful connections (Associated state) achieved by all clients during the test when WiFi is re-enabled.
" - # " Here real clients used is "+ str(self.clients) + "and number of resets provided is " + str(self.reset) + # " Here real clients used is "+ str(self.clients) + "and number of resets provided is " + str(self.reset_count) ) self.lf_report.build_objective() for coordinate in range(len(self.coordinate_list)): @@ -1583,8 +1580,8 @@ def generate_report_for_robo(self): "Port Resets": self.total_resets, "Disconnects": self.total_disconnects, "Scans": self.total_scans, - "Assoc Attemts": self.total_ass_attemst, - "Assoc Rejects": self.total_ass_rejects, + "Assoc Attemts": self.total_assoc_attempts, + "Assoc Rejects": self.total_assoc_rejections, "Connects": self.total_connects } test_setup = pd.DataFrame(table_2) @@ -1647,8 +1644,8 @@ def generate_report_for_robo(self): "Port Resets": self.total_resets, "Disconnects": self.total_disconnects, "Scans": self.total_scans, - "Assoc Attemts": self.total_ass_attemst, - "Assoc Rejects": self.total_ass_rejects, + "Assoc Attemts": self.total_assoc_attempts, + "Assoc Rejects": self.total_assoc_rejections, "Connects": self.total_connects } test_setup = pd.DataFrame(table_2) @@ -1839,57 +1836,52 @@ def main(): logger_config.lf_logger_config_json = args.lf_logger_config_json logger_config.load_lf_logger_config() - obj = InteropPortReset(host=args.host, - port=args.port, - dut=args.dut, - ssid=args.ssid, - passwd=args.passwd, - encryp=args.encryp, - reset=args.reset, - # clients=args.clients, - time_int=args.time_int, - # wait_time=args.wait_time, - suporrted_release=args.release, - mgr_ip=args.mgr_ip, - device_list=args.device_list, - forget_network=not args.no_forget_networks, - dowebgui=args.dowebgui, - result_dir=args.result_dir, - test_name=args.test_name, - robot_test=args.robot_test, - robot_ip=args.robot_ip, - robot_port=args.robot_port, - coordinate=args.coordinate, - rotation=args.rotation, - get_live_view=args.get_live_view, - total_floors=args.total_floors - ) - - # mgr_ip may have been given as a port name (e.g. "eth1") rather than an IP; - # resolve it now that we have an instance to reuse for the LANforge lookup. - # base_interop_profile.server_ip was already captured from the unresolved - # mgr_ip at construction time above, so it must be patched too. - obj.mgr_ip = obj.change_port_to_ip(obj.mgr_ip) - obj.base_interop_profile.server_ip = obj.mgr_ip - print(obj.mgr_ip) - - obj.selecting_devices_from_available() - if obj.robot_test: - obj.run() + port_reset_test = InteropPortReset(host=args.host, + port=args.port, + dut=args.dut, + ssid=args.ssid, + passwd=args.passwd, + encryption=args.encryp, + reset_count=args.reset, + # clients=args.clients, + reset_interval_sec=args.time_int, + supported_release=args.release, + mgr_ip=args.mgr_ip, + device_list=args.device_list, + forget_network=not args.no_forget_networks, + dowebgui=args.dowebgui, + result_dir=args.result_dir, + test_name=args.test_name, + robot_test=args.robot_test, + robot_ip=args.robot_ip, + robot_port=args.robot_port, + coordinate=args.coordinate, + rotation=args.rotation, + get_live_view=args.get_live_view, + total_floors=args.total_floors + ) + + port_reset_test.mgr_ip = port_reset_test.change_port_to_ip(port_reset_test.mgr_ip) + port_reset_test.base_interop_profile.server_ip = port_reset_test.mgr_ip + print(port_reset_test.mgr_ip) + + port_reset_test.selecting_devices_from_available() + if port_reset_test.robot_test: + port_reset_test.run() else: - reset_dict, duration = obj.run() + per_iteration_results, test_duration = port_reset_test.run() if args.dowebgui: - obj.result_df['Status'] = 'stopped' - if obj.robot_test: - obj.result_df.to_csv(f"{obj.report_path}/overall_reset_{obj.current_coordinate}.csv", index=False) - obj.result_df.to_csv(f"{obj.result_dir}/overall_reset_{obj.current_coordinate}.csv", index=False) + port_reset_test.result_df['Status'] = 'stopped' + if port_reset_test.robot_test: + port_reset_test.result_df.to_csv(f"{port_reset_test.report_path}/overall_reset_{port_reset_test.current_coordinate}.csv", index=False) + port_reset_test.result_df.to_csv(f"{port_reset_test.result_dir}/overall_reset_{port_reset_test.current_coordinate}.csv", index=False) else: - obj.result_df.to_csv(f"{obj.report_path}/overall_reset.csv", index=False) - obj.result_df.to_csv(f"{obj.result_dir}/overall_reset.csv", index=False) - if obj.robot_test: - obj.generate_report_for_robo() + port_reset_test.result_df.to_csv(f"{port_reset_test.report_path}/overall_reset.csv", index=False) + port_reset_test.result_df.to_csv(f"{port_reset_test.result_dir}/overall_reset.csv", index=False) + if port_reset_test.robot_test: + port_reset_test.generate_report_for_robo() else: - obj.generate_report(reset_dict=reset_dict, test_dur=duration) + port_reset_test.generate_report(reset_dict=per_iteration_results, test_dur=test_duration) if __name__ == '__main__': From 3de648edfb9450049b6779d09bf040b04132d2cd Mon Sep 17 00:00:00 2001 From: Narayana-CT Date: Thu, 20 Aug 2026 17:53:55 +0530 Subject: [PATCH 02/13] lf_interop_port_reset_test.py: rename CLI arguments to say what they carry Signed-off-by: Narayana-CT --- py-scripts/lf_interop_port_reset_test.py | 139 ++++++++++++----------- 1 file changed, 71 insertions(+), 68 deletions(-) diff --git a/py-scripts/lf_interop_port_reset_test.py b/py-scripts/lf_interop_port_reset_test.py index 351830bc4..0615cd6a9 100755 --- a/py-scripts/lf_interop_port_reset_test.py +++ b/py-scripts/lf_interop_port_reset_test.py @@ -11,18 +11,18 @@ EXAMPLE: # To run port-reset test on specified real devices (android, laptops) - ./lf_interop_port_reset_test.py --host 192.168.200.192 --mgr_ip 192.168.1.161 --dut TestDut --ssid OpenWifi - --passwd OpenWifi --encryp psk2 --reset 10 --time_int 5 --release 11 + ./lf_interop_port_reset_test.py --lanforge_ip 192.168.200.192 --upstream_port 192.168.1.161 --dut TestDut --ssid OpenWifi + --passwd OpenWifi --encryp psk2 --iterations 10 --reset_interval 5 --android_releases 11 # To run port-reset test on specified real devices with only coordinates - ./lf_interop_port_reset_test.py --host 192.168.207.78 --mgr_ip eth1 --dut AP --ssid "NETGEAR_2G_wpa2" --encryp psk2 --passwd Password@123 - --reset 2 --time_int 5 --robot_test --coordinate 4,3 --robot_ip 192.168.200.169 --device_list ubuntu24 + ./lf_interop_port_reset_test.py --lanforge_ip 192.168.207.78 --upstream_port eth1 --dut AP --ssid "NETGEAR_2G_wpa2" --encryp psk2 --passwd Password@123 + --iterations 2 --reset_interval 5 --robot_test --coordinate 4,3 --robot_ip 192.168.200.169 --device_list ubuntu24 # To run port-reset test on specified real devices with only coordinates and rotations - ./lf_interop_port_reset_test.py --host 192.168.207.78 --mgr_ip eth1 --dut AP --ssid "NETGEAR_2G_wpa2" --encryp psk2 --passwd Password@123 - --reset 2 --time_int 5 --robot_test --coordinate 4,3 --rotation 30,45 --robot_ip 192.168.200.169 --device_list ubuntu24 + ./lf_interop_port_reset_test.py --lanforge_ip 192.168.207.78 --upstream_port eth1 --dut AP --ssid "NETGEAR_2G_wpa2" --encryp psk2 --passwd Password@123 + --iterations 2 --reset_interval 5 --robot_test --coordinate 4,3 --rotation 30,45 --robot_ip 192.168.200.169 --device_list ubuntu24 SCRIPT_CLASSIFICATION: Toggling, Report Generation, Each Reset Wi-Fi Messages @@ -80,17 +80,17 @@ class InteropPortReset(Realm): - def __init__(self, host, - port=8080, + def __init__(self, lanforge_ip, + lanforge_port=8080, dut=None, ssid=None, passwd=None, encryption=None, - reset_count=None, - mgr_ip=None, + iterations=None, + upstream_port=None, reset_interval_sec=None, device_list=None, - supported_release=None, + android_releases=None, forget_network=True, dowebgui=False, result_dir=None, @@ -103,7 +103,7 @@ def __init__(self, host, get_live_view=False, total_floors=0, ): - super().__init__(lfclient_host=host, + super().__init__(lfclient_host=lanforge_ip, lfclient_port=8080) self.total_connects = [] self.total_assoc_rejections = [] @@ -122,15 +122,15 @@ def __init__(self, host, self.linux_list = [] self.mac_list = [] self.encrypt_value = 0 - self.host = host - self.port = port + self.lanforge_ip = lanforge_ip + self.lanforge_port = lanforge_port self.android_serials = [] self.dut_name = dut self.ssid = ssid self.passwd = passwd self.encryption = encryption - self.mgr_ip = mgr_ip - self.reset_count = reset_count + self.upstream_port = upstream_port + self.iterations = iterations self.reset_interval_sec = reset_interval_sec self.device_list = device_list self.forget_network = forget_network @@ -153,17 +153,17 @@ def __init__(self, host, self.rotation_list = rotation.split(',') self.current_coordinate = None self.current_angle = None - self.supported_release = supported_release + self.android_releases = android_releases self.android_user_names = [] self.lf_report = lf_report_pdf.lf_report(_path="" if not self.dowebgui else self.result_dir, _results_dir_name="Interop_port_reset_test", _output_html="port_reset_test.html", _output_pdf="port_reset_test.pdf") self.report_path = self.lf_report.get_report_path() - self.base_interop_profile = base.RealDevice(manager_ip=self.host, server_ip=self.mgr_ip, ssid_5g=self.ssid, + self.base_interop_profile = base.RealDevice(manager_ip=self.lanforge_ip, server_ip=self.upstream_port, ssid_5g=self.ssid, encryption_5g=self.encryption, passwd_5g=self.passwd, disconnect_devices=self.forget_network, reboot=False, selected_bands=["5g"]) - self.utility = base.UtilityInteropWifi(host_ip=self.host) + self.utility = base.UtilityInteropWifi(host_ip=self.lanforge_ip) # logging.basicConfig(filename='port_reset.log', filemode='w', format='%(asctime)s - %(message)s', # level=logging.INFO, force=True) @@ -189,7 +189,7 @@ def json_get_with_retry(self, url, wait_time=40, poll_interval=5, debug_=False): def change_port_to_ip(self, upstream_port): # Resolves an ethernet port name (e.g. "eth1") to its IP via LANforge, used - # for --mgr_ip. This is only called once, at test start, and we cannot + # for --upstream_port. This is only called once, at test start, and we cannot # proceed without a resolved manager IP, so retry for a while and then # abort instead of silently continuing with an unresolved port name. if upstream_port.count('.') != 3: @@ -231,12 +231,12 @@ def selecting_devices_from_available(self): raise ValueError('Real station not in devices data') android_list = self.base_interop_profile.android_list - self.interop = base.BaseInteropWifi(manager_ip=self.host, - port=self.port, + self.interop = base.BaseInteropWifi(manager_ip=self.lanforge_ip, + port=self.lanforge_port, ssid=self.ssid, passwd=self.passwd, encryption=self.encryption, - release=self.supported_release, + release=self.android_releases, screen_size_prcnt=0.4, _debug_on=False, _exit_on_error=False) @@ -703,7 +703,7 @@ def generate_coordinate_csv(self, reset_dict, r): def performing_resets(self, test_start_time=None): reset_list = [] - for i in range(self.reset_count): + for i in range(self.iterations): reset_list.append(i) logging.info(f"Given No.of iterations for Reset : {len(reset_list)}") logging.info("Reset list:" + str(reset_list)) @@ -712,7 +712,7 @@ def performing_resets(self, test_start_time=None): interval = 300 test_stopped_by_user = False charge_check = time.time() + interval - for r, _ in zip(range(self.reset_count), reset_dict): + for r, _ in zip(range(self.iterations), reset_dict): if self.robot_test: current_time = time.time() if current_time >= charge_check: @@ -737,7 +737,7 @@ def performing_resets(self, test_start_time=None): test_stopped_by_user = True break charge_check = current_time + interval - logging.info(f"Waiting until given {self.reset_interval_sec} sec time intervel to finish...") + logging.info(f"Waiting until given {self.reset_interval_sec} sec time interval to finish...") time.sleep(int(self.reset_interval_sec)) # sleeping until time interval finish logging.info(f"Iteration :- {r}") logging.info("Reset -" + str(r)) @@ -798,7 +798,7 @@ def performing_resets(self, test_start_time=None): else: self.create_dict_csv(reset_dict) if self.dowebgui: - with open(self.result_dir + f"/../../Running_instances/{self.host}_{self.test_name}_running.json", + with open(self.result_dir + f"/../../Running_instances/{self.lanforge_ip}_{self.test_name}_running.json", 'r') as file: data = json.load(file) if data["status"] != "Running": @@ -818,7 +818,7 @@ def performing_resets(self, test_start_time=None): 'cx time (us)': 0 } keys_to_delete = [] - for i in range(self.reset_count): + for i in range(self.iterations): if reset_dict.get(i) is None: keys_to_delete.append(i) else: @@ -950,7 +950,7 @@ def run(self): nav_data = os.path.join(base_dir, 'nav_data.json') # To generate nav_data.json in webgui folder self.robot_obj.nav_data_path = nav_data self.robot_obj.create_waypointlist() - self.robot_obj.ip = self.host + self.robot_obj.ip = self.lanforge_ip self.robot_obj.testname = self.test_name self.robot_obj.runtime_dir = self.result_dir test_stopped_by_user = False @@ -1000,7 +1000,7 @@ def generate_overall_graph(self, reset_dict=None, figsize=(13, 5), _alignmen=Non _legend_fontsize=None, text_font=12, bar_text_rotation=45, graph_suffix=""): dict_ = ['Port Resets', 'Disconnected', 'Scans', 'Assoc Attempts', "Association Rejection", 'Connected'] data = dict.fromkeys(dict_) - data['Port Resets'] = self.reset_count * len(self.all_selected_devices) + data['Port Resets'] = self.iterations * len(self.all_selected_devices) conected_list, laptop_conected_list = [], [] disconnected_list, laptop_disconnected_list = [], [] @@ -1179,7 +1179,7 @@ def generate_overall_graph_table(self, reset_dict, device_list): dict_ = ['Port Resets', 'Disconnects', 'Scans', 'Association Attempts', "Association Rejections", 'Connects'] data = dict.fromkeys(dict_) - data['Port Resets'] = self.reset_count + data['Port Resets'] = self.iterations dis = 0 for i in disconnected: @@ -1209,7 +1209,7 @@ def generate_overall_graph_table(self, reset_dict, device_list): # print(f"Final data for per client graph for {y}: {data}") # fetching the total dissconnects, connects, ass_attemsts, ass_rejections, scans - self.total_resets.append(self.reset_count) + self.total_resets.append(self.iterations) self.total_disconnects.append(sum(disconnected)) self.total_scans.append(sum(scanning)) self.total_assoc_attempts.append(sum(asso_attempts)) @@ -1239,7 +1239,7 @@ def individual_client_info(self, reset_dict, device_list): dict_ = ['Port Resets', 'Disconnects', 'Scans', 'Association Attempts', "Association Rejections", 'Connects'] data = dict.fromkeys(dict_) - data['Port Resets'] = self.reset_count + data['Port Resets'] = self.iterations dis = 0 for i in disconnected: @@ -1327,13 +1327,13 @@ def generate_report(self, reset_dict=None, test_dur=None): security = "open" test_setup_info = { "DUT Name": self.dut_name, - "LANforge ip": self.host, + "LANforge ip": self.lanforge_ip, "SSID": self.ssid, "Security": security, - "Total Reset Count": self.reset_count, + "Total Reset Count": self.iterations, "No of Clients": f"{len(self.all_selected_devices)} (Windows: {len(self.windows_list)}, Linux: {len(self.linux_list)}, Mac: {len(self.mac_list)}, Android: {len(self.adb_device_list)})", # noqa: E501 # "Wait Time": str(self.wait_time) + " sec", - "Time intervel between resets": str(self.reset_interval_sec) + " sec", + "Time interval between resets": str(self.reset_interval_sec) + " sec", "Test Duration": test_dur, } self.lf_report.set_title("Port Reset Test") @@ -1365,7 +1365,7 @@ def generate_report(self, reset_dict=None, test_dur=None): "4. Association Attempts: Total number of association attempts (Associating state) made by all clients after WiFi is re-enabled in the full test.
" "4. Association Rejections: Total number of association rejections made by all clients after WiFi is re-enabled in the full test.
" "6. Connected: Total number of successful connections (Associated state) achieved by all clients during the test when WiFi is re-enabled.
" - # " Here real clients used is "+ str(self.clients) + "and number of resets provided is " + str(self.reset_count) + # " Here real clients used is "+ str(self.clients) + "and number of resets provided is " + str(self.iterations) ) self.lf_report.build_objective() graph1 = self.generate_overall_graph(reset_dict=reset_dict, figsize=(13, 5), _alignmen=None, bar_width=0.5, @@ -1472,13 +1472,13 @@ def generate_report_for_robo(self): security = "open" test_setup_info = { "DUT Name": self.dut_name, - "LANforge ip": self.host, + "LANforge ip": self.lanforge_ip, "SSID": self.ssid, "Security": security, - "Total Reset Count": self.reset_count, + "Total Reset Count": self.iterations, "No of Clients": f"{len(self.all_selected_devices)} (Windows: {len(self.windows_list)}, Linux: {len(self.linux_list)}, Mac: {len(self.mac_list)}, Android: {len(self.adb_device_list)})", # noqa: E501 # "Wait Time": str(self.wait_time) + " sec", - "Time intervel between resets": str(self.reset_interval_sec) + " sec", + "Time interval between resets": str(self.reset_interval_sec) + " sec", } test_setup_info["Selected Coordinates"] = self.coordinate if self.rotation_enabled: @@ -1515,7 +1515,7 @@ def generate_report_for_robo(self): "4. Association Attempts: Total number of association attempts (Associating state) made by all clients after WiFi is re-enabled in the full test.
" "4. Association Rejections: Total number of association rejections made by all clients after WiFi is re-enabled in the full test.
" "6. Connected: Total number of successful connections (Associated state) achieved by all clients during the test when WiFi is re-enabled.
" - # " Here real clients used is "+ str(self.clients) + "and number of resets provided is " + str(self.reset_count) + # " Here real clients used is "+ str(self.clients) + "and number of resets provided is " + str(self.iterations) ) self.lf_report.build_objective() for coordinate in range(len(self.coordinate_list)): @@ -1711,6 +1711,7 @@ def main(): parser = argparse.ArgumentParser( prog=__file__, formatter_class=argparse.RawTextHelpFormatter, + allow_abbrev=False, description=''' NAME: lf_interop_port_reset_test.py @@ -1723,18 +1724,18 @@ def main(): EXAMPLE: # To run port-reset test on specified real devices (android, laptops) - python3 lf_interop_port_reset_test.py --host 192.168.200.63 --mgr_ip 192.168.1.61 --dut Test_Dut - --ssid RDT_wpa2 --passwd OpenWifi --encryp psk2 --reset 1 --time_int 5 --release 11 + python3 lf_interop_port_reset_test.py --lanforge_ip 192.168.200.63 --upstream_port 192.168.1.61 --dut Test_Dut + --ssid RDT_wpa2 --passwd OpenWifi --encryp psk2 --iterations 1 --reset_interval 5 --android_releases 11 # To run port-reset test on specified real devices with only coordinates - python3 lf_interop_port_reset_test.py --host 192.168.207.78 --mgr_ip eth1 --dut AP --ssid "NETGEAR_2G_wpa2" --encryp psk2 --passwd Password@123 - --reset 2 --time_int 5 --robot_test --coordinate 4,3 --robot_ip 192.168.200.169 --device_list ubuntu24 + python3 lf_interop_port_reset_test.py --lanforge_ip 192.168.207.78 --upstream_port eth1 --dut AP --ssid "NETGEAR_2G_wpa2" --encryp psk2 --passwd Password@123 + --iterations 2 --reset_interval 5 --robot_test --coordinate 4,3 --robot_ip 192.168.200.169 --device_list ubuntu24 # To run port-reset test on specified real devices with only coordinates and rotations - python3 lf_interop_port_reset_test.py --host 192.168.207.78 --mgr_ip eth1 --dut AP --ssid "NETGEAR_2G_wpa2" --encryp psk2 --passwd Password@123 - --reset 2 --time_int 5 --robot_test --coordinate 4,3 --rotation 30,45 --robot_ip 192.168.200.169 --device_list ubuntu24 + python3 lf_interop_port_reset_test.py --lanforge_ip 192.168.207.78 --upstream_port eth1 --dut AP --ssid "NETGEAR_2G_wpa2" --encryp psk2 --passwd Password@123 + --iterations 2 --reset_interval 5 --robot_test --coordinate 4,3 --rotation 30,45 --robot_ip 192.168.200.169 --device_list ubuntu24 SCRIPT_CLASSIFICATION: Interop Port-Reset Test @@ -1760,13 +1761,14 @@ def main(): INCLUDE_IN_README: False ''') - parser.add_argument("--host", default='192.168.1.31', - help='Specify the GUI to connect to, assumes port 8080') + parser.add_argument("--lanforge_ip", default='192.168.1.31', + help='Specify the LANforge GUI to connect to, assumes port 8080') - parser.add_argument("--port", default='8080', help='Specify the manager port') + parser.add_argument("--lanforge_port", default='8080', help='Specify the LANforge manager HTTP port') - parser.add_argument("--mgr_ip", default='192.168.1.31', - help='Specify the interop manager ip') + parser.add_argument("--upstream_port", default='192.168.1.31', + help='Specify the upstream port feeding the DUT, either as a port name ' + '(e.g. eth1) or as its IP') parser.add_argument("--dut", default="TestDut", help='Specify DUT name on which the test will be running.') @@ -1780,11 +1782,11 @@ def main(): parser.add_argument("--encryp", default="psk2", help='Specify the encryption type on which the test will be running eg :open|psk|psk2|sae|psk2jsae') - parser.add_argument("--reset", type=int, default=2, - help='Specify the number of time you want to reset. eg: 2') + parser.add_argument("--iterations", type=int, default=2, + help='Specify how many reset iterations to run. eg: 2') - parser.add_argument("--time_int", type=int, default=5, - help='Specify the time interval in seconds after which reset should happen.') + parser.add_argument("--reset_interval", type=int, default=5, + help='Specify the time interval in seconds to wait between reset iterations.') parser.add_argument('--device_list', help='Enter the devices on which the test should be run', default=None) @@ -1795,9 +1797,10 @@ def main(): # parser.add_argument("--wait_time", type=int, default=20, # help='Specify the wait time in seconds for WIFI Supplicant Logs.') - parser.add_argument("--release", nargs='*', default=["12"], - help='Specify the SDK release version (Android Version) of real clients to be supported in test.' - 'eg:- --release 11 12 13') + parser.add_argument("--android_releases", nargs='*', default=["12"], + help='Specify which Android releases (SDK versions) may take part in the test; android ' + 'devices on any other release are skipped. Laptops are unaffected. ' + 'eg:- --android_releases 11 12 13') # logging configuration: parser.add_argument('--log_level', default=None, help='Set logging level: debug | info | warning | error | critical') @@ -1836,17 +1839,17 @@ def main(): logger_config.lf_logger_config_json = args.lf_logger_config_json logger_config.load_lf_logger_config() - port_reset_test = InteropPortReset(host=args.host, - port=args.port, + port_reset_test = InteropPortReset(lanforge_ip=args.lanforge_ip, + lanforge_port=args.lanforge_port, dut=args.dut, ssid=args.ssid, passwd=args.passwd, encryption=args.encryp, - reset_count=args.reset, + iterations=args.iterations, # clients=args.clients, - reset_interval_sec=args.time_int, - supported_release=args.release, - mgr_ip=args.mgr_ip, + reset_interval_sec=args.reset_interval, + android_releases=args.android_releases, + upstream_port=args.upstream_port, device_list=args.device_list, forget_network=not args.no_forget_networks, dowebgui=args.dowebgui, @@ -1861,9 +1864,9 @@ def main(): total_floors=args.total_floors ) - port_reset_test.mgr_ip = port_reset_test.change_port_to_ip(port_reset_test.mgr_ip) - port_reset_test.base_interop_profile.server_ip = port_reset_test.mgr_ip - print(port_reset_test.mgr_ip) + port_reset_test.upstream_port = port_reset_test.change_port_to_ip(port_reset_test.upstream_port) + port_reset_test.base_interop_profile.server_ip = port_reset_test.upstream_port + print(port_reset_test.upstream_port) port_reset_test.selecting_devices_from_available() if port_reset_test.robot_test: From a72a286af4c425907d4db4587532da7d02a7bb2b Mon Sep 17 00:00:00 2001 From: Narayana-CT Date: Fri, 21 Aug 2026 12:17:38 +0530 Subject: [PATCH 03/13] lf_interop_port_reset_test.py: clarify naming in selecting_devices_from_available(), performing_resets() and run() Signed-off-by: Narayana-CT --- py-scripts/lf_interop_port_reset_test.py | 306 +++++++++++------------ 1 file changed, 153 insertions(+), 153 deletions(-) diff --git a/py-scripts/lf_interop_port_reset_test.py b/py-scripts/lf_interop_port_reset_test.py index 0615cd6a9..5293adcd6 100755 --- a/py-scripts/lf_interop_port_reset_test.py +++ b/py-scripts/lf_interop_port_reset_test.py @@ -212,21 +212,22 @@ def change_port_to_ip(self, upstream_port): def selecting_devices_from_available(self): # If device list is not provided by user, then it shows the available devices to choose from if self.device_list is None: - devices = self.base_interop_profile.query_all_devices_to_configure_wifi() + configurable_devices = self.base_interop_profile.query_all_devices_to_configure_wifi() else: - devices = self.base_interop_profile.query_all_devices_to_configure_wifi(device_list=self.device_list.split(',')) - asyncio.run(self.base_interop_profile.configure_wifi(devices[0] + devices[1] + devices[2])) - self.real_sta_list = self.base_interop_profile.station_list - logger.info(self.real_sta_list) - real_device_data = self.base_interop_profile.devices_data - if len(self.real_sta_list) == 0: + configurable_devices = self.base_interop_profile.query_all_devices_to_configure_wifi(device_list=self.device_list.split(',')) + asyncio.run(self.base_interop_profile.configure_wifi( + configurable_devices[0] + configurable_devices[1] + configurable_devices[2])) + self.real_station_list = self.base_interop_profile.station_list + logger.info(self.real_station_list) + device_details = self.base_interop_profile.devices_data + if len(self.real_station_list) == 0: logging.error('There are no real devices in this testbed. Aborting the test.') - # Added for the purpose to stop webui test when there are no selected devices availble in lanforge. - raise RuntimeError("here are no real devices in this testbed. Aborting the test.") - logging.info(f"{self.real_sta_list}") + # Added for the purpose to stop webui test when there are no selected devices available in lanforge. + raise RuntimeError("There are no real devices in this testbed. Aborting the test.") + logging.info(f"{self.real_station_list}") - for sta_name in self.real_sta_list: - if sta_name not in real_device_data: + for station_name in self.real_station_list: + if station_name not in device_details: logger.error('Real Station not in devices data') raise ValueError('Real station not in devices data') android_list = self.base_interop_profile.android_list @@ -240,13 +241,13 @@ def selecting_devices_from_available(self): screen_size_prcnt=0.4, _debug_on=False, _exit_on_error=False) - supported_dict = self.interop.supported_devices_resource_id - print("Supported dict", supported_dict) + supported_resource_ids = self.interop.supported_devices_resource_id + print("Supported dict", supported_resource_ids) self.final_selected_android_list = [] - for key in supported_dict.keys(): - if key != "": - if any(key in item for item in android_list): - self.final_selected_android_list.append(supported_dict[key]) + for device_name in supported_resource_ids.keys(): + if device_name != "": + if any(device_name in item for item in android_list): + self.final_selected_android_list.append(supported_resource_ids[device_name]) logging.info(f"Final Android Serial Numbers List: {self.final_selected_android_list}") def create_log_file(self, json_list, file_name="empty.json"): @@ -702,26 +703,26 @@ def generate_coordinate_csv(self, reset_dict, r): df.to_csv(f"{self.result_dir}/overall_reset_{self.current_coordinate}.csv", index=False) def performing_resets(self, test_start_time=None): - reset_list = [] - for i in range(self.iterations): - reset_list.append(i) - logging.info(f"Given No.of iterations for Reset : {len(reset_list)}") - logging.info("Reset list:" + str(reset_list)) - reset_dict = dict.fromkeys(reset_list) + iteration_indexes = [] + for index in range(self.iterations): + iteration_indexes.append(index) + logging.info(f"Given No.of iterations for Reset : {len(iteration_indexes)}") + logging.info("Reset list:" + str(iteration_indexes)) + per_iteration_results = dict.fromkeys(iteration_indexes) test_stopped = False - interval = 300 + battery_check_interval_sec = 300 test_stopped_by_user = False - charge_check = time.time() + interval - for r, _ in zip(range(self.iterations), reset_dict): + next_battery_check = time.time() + battery_check_interval_sec + for iteration, _ in zip(range(self.iterations), per_iteration_results): if self.robot_test: current_time = time.time() - if current_time >= charge_check: + if current_time >= next_battery_check: if test_stopped_by_user or self.robo_test_stopped: break - pause, test_stopped_by_user = self.robot_obj.wait_for_battery() + paused, test_stopped_by_user = self.robot_obj.wait_for_battery() if test_stopped_by_user: break - if pause: + if paused: # After charging, return to the last coordinate reached, abort = self.robot_obj.move_to_coordinate(self.current_coordinate) # If user stopped the test during movement @@ -732,83 +733,85 @@ def performing_resets(self, test_start_time=None): break # Restore orientation if rotation is enabled if self.rotation_enabled: - rotation_moni = self.robot_obj.rotate_angle(self.current_angle) - if not rotation_moni: + rotated = self.robot_obj.rotate_angle(self.current_angle) + if not rotated: test_stopped_by_user = True break - charge_check = current_time + interval + next_battery_check = current_time + battery_check_interval_sec logging.info(f"Waiting until given {self.reset_interval_sec} sec time interval to finish...") time.sleep(int(self.reset_interval_sec)) # sleeping until time interval finish - logging.info(f"Iteration :- {r}") - logging.info("Reset -" + str(r)) - local_dict = dict.fromkeys(self.adb_device_list) - logging.info(f"local dict for android :{local_dict}") - laptop_local_dict = dict.fromkeys(self.all_laptops) - logging.info(f"local dict for laptops : {laptop_local_dict}") - local_dict.update(laptop_local_dict) - - list_ = ["ConnectAttempt", "Disconnected", "Scanning", "Association Rejection", "Connected"] - sec_dict = dict.fromkeys(list_) - - for i in self.adb_device_list: - local_dict[i] = sec_dict.copy() # for android devices dict - for i in self.all_laptops: - laptop_local_dict[i] = sec_dict.copy() # for laptop devices dict - logging.info(f"Final Outcome dict for android devices: {local_dict}") - logging.info(f"Final Outcome dict for laptop devices: {laptop_local_dict}") - logging.info(str(local_dict)) - - local_dict.update(laptop_local_dict) - logging.info(f"Final dict: {local_dict}") + logging.info(f"Iteration :- {iteration}") + logging.info("Reset -" + str(iteration)) + device_metrics = dict.fromkeys(self.adb_device_list) + logging.info(f"local dict for android :{device_metrics}") + laptop_metrics = dict.fromkeys(self.all_laptops) + logging.info(f"local dict for laptops : {laptop_metrics}") + device_metrics.update(laptop_metrics) + + metric_names = ["ConnectAttempt", "Disconnected", "Scanning", "Association Rejection", "Connected"] + empty_metrics = dict.fromkeys(metric_names) + + for device_eid in self.adb_device_list: + device_metrics[device_eid] = empty_metrics.copy() # for android devices dict + for device_eid in self.all_laptops: + laptop_metrics[device_eid] = empty_metrics.copy() # for laptop devices dict + logging.info(f"Final Outcome dict for android devices: {device_metrics}") + logging.info(f"Final Outcome dict for laptop devices: {laptop_metrics}") + logging.info(str(device_metrics)) + + device_metrics.update(laptop_metrics) + logging.info(f"Final dict: {device_metrics}") # note last log time - timee = self.get_last_wifi_msg() - - for i in self.adb_device_list: - self.interop.stop(device=i) - for i in self.all_laptops: # laptop admin down - logging.info(f"**** Disable wifi for laptop {i}") - self.admin_down(port_eid=i) - for i in self.adb_device_list: - logging.info(f"**** Disable wifi for android {i}") + since_time = self.get_last_wifi_msg() + + for device_eid in self.adb_device_list: + self.interop.stop(device=device_eid) + for device_eid in self.all_laptops: # laptop admin down + logging.info(f"**** Disable wifi for laptop {device_eid}") + self.admin_down(port_eid=device_eid) + for device_eid in self.adb_device_list: + logging.info(f"**** Disable wifi for android {device_eid}") logging.info("disable wifi") - self.interop.enable_or_disable_wifi(device=i, wifi="disable") - for i in self.all_laptops: # laptop admin up - logging.info(f"**** Enable wifi for laptop {i}") - self.admin_up(port_eid=i) - for i in self.adb_device_list: - logging.info(f"*** Enable wifi for laptop {i}") + self.interop.enable_or_disable_wifi(device=device_eid, wifi="disable") + for device_eid in self.all_laptops: # laptop admin up + logging.info(f"**** Enable wifi for laptop {device_eid}") + self.admin_up(port_eid=device_eid) + for device_eid in self.adb_device_list: + logging.info(f"*** Enable wifi for laptop {device_eid}") logging.info("enable wifi") - self.interop.enable_or_disable_wifi(device=i, wifi="enable") - for i in self.adb_device_list: - logging.info(f"Starting APP for {i}") - self.interop.start(device=i) + self.interop.enable_or_disable_wifi(device=device_eid, wifi="enable") + for device_eid in self.adb_device_list: + logging.info(f"Starting APP for {device_eid}") + self.interop.start(device=device_eid) if self.all_laptops: if self.wait_for_ip(station_list=self.all_laptops, timeout_sec=60): logging.info("PASSED : ALL STATIONS GOT IP") else: logging.info("FAILED : MAY BE NOT ALL STATIONS ACQUIRED IP'S") time.sleep(30) - for i in self.all_selected_devices: - get_dicct = self.get_time_from_wifi_msgs(local_dict=local_dict, phn_name=i, timee=timee, - file_name=f"reset_{r}_log.json", reset_cnt=r) - reset_dict[r] = get_dicct + for device_eid in self.all_selected_devices: + iteration_metrics = self.get_time_from_wifi_msgs(local_dict=device_metrics, phn_name=device_eid, + timee=since_time, + file_name=f"reset_{iteration}_log.json", + reset_cnt=iteration) + per_iteration_results[iteration] = iteration_metrics if self.robot_test: - self.generate_coordinate_csv(reset_dict=reset_dict, r=r) + self.generate_coordinate_csv(reset_dict=per_iteration_results, r=iteration) else: - self.create_dict_csv(reset_dict) + self.create_dict_csv(per_iteration_results) if self.dowebgui: with open(self.result_dir + f"/../../Running_instances/{self.lanforge_ip}_{self.test_name}_running.json", 'r') as file: - data = json.load(file) - if data["status"] != "Running": + run_status = json.load(file) + if run_status["status"] != "Running": logging.info('Test is stopped by the user') test_stopped = True self.robo_test_stopped = True break - logging.info('{}'.format(reset_dict)) + logging.info('{}'.format(per_iteration_results)) if test_stopped: - temp_data = { + stopped_metrics = { 'ConnectAttempt': 0, 'Disconnected': 0, 'Scanning': 0, @@ -817,21 +820,21 @@ def performing_resets(self, test_start_time=None): 'Remarks': "Test stopped by user", 'cx time (us)': 0 } - keys_to_delete = [] - for i in range(self.iterations): - if reset_dict.get(i) is None: - keys_to_delete.append(i) + empty_iterations = [] + for iteration_index in range(self.iterations): + if per_iteration_results.get(iteration_index) is None: + empty_iterations.append(iteration_index) else: - for dev, data in reset_dict[i].items(): - if any(v is None for v in data.values()): - reset_dict[i][dev] = temp_data.copy() + for device_eid, metrics in per_iteration_results[iteration_index].items(): + if any(value is None for value in metrics.values()): + per_iteration_results[iteration_index][device_eid] = stopped_metrics.copy() - for key in keys_to_delete: - del reset_dict[key] + for iteration_index in empty_iterations: + del per_iteration_results[iteration_index] break - logging.info(f"Final Reset Count Dictionary for all clients: {reset_dict}") - logging.info("reset dict " + str(reset_dict)) + logging.info(f"Final Reset Count Dictionary for all clients: {per_iteration_results}") + logging.info("reset dict " + str(per_iteration_results)) test_end = datetime.now() test_end_time = test_end.strftime("%b %d %H:%M:%S") if self.robot_test: @@ -842,10 +845,8 @@ def performing_resets(self, test_start_time=None): else: logging.info(f"Test Ended at {test_end}") # logging.info("Test ended at " + test_end_time) - s1 = test_start_time - s2 = test_end_time - FMT = '%b %d %H:%M:%S' - test_duration = datetime.strptime(s2, FMT) - datetime.strptime(s1, FMT) + time_format = '%b %d %H:%M:%S' + test_duration = datetime.strptime(test_end_time, time_format) - datetime.strptime(test_start_time, time_format) if self.robot_test: if self.rotation_enabled: logging.info(f"Total Test Duration taken to complete port resets at coordinate {self.current_coordinate} on angle {self.current_angle}: {test_duration}") @@ -854,15 +855,15 @@ def performing_resets(self, test_start_time=None): else: logging.info(f"Total Test Duration: {test_duration}") - return reset_dict, test_duration + return per_iteration_results, test_duration # @property def run(self): try: # start timer - present_time = datetime.now() - test_start_time = present_time.strftime("%b %d %H:%M:%S") - logging.info(f"Test Started at {present_time}") + test_start = datetime.now() + test_start_time = test_start.strftime("%b %d %H:%M:%S") + logging.info(f"Test Started at {test_start}") self.adb_device_list = self.interop.check_sdk_release(selected_android_devices=self.final_selected_android_list) self.windows_list = self.base_interop_profile.windows_list self.linux_list = self.base_interop_profile.linux_list @@ -887,59 +888,58 @@ def run(self): # Added for the purpose to stop webui test when there are no selected devices availble in lanforge. raise RuntimeError("There is no active devices please check system.") else: - for i in range(len(self.adb_device_list)): - self.android_serials.append(self.adb_device_list[i].split(".")[2]) + for index in range(len(self.adb_device_list)): + self.android_serials.append(self.adb_device_list[index].split(".")[2]) logging.info(f"Separated device names from the full name: {self.android_serials}") # check status of devices - phantom = [] - for i in self.adb_device_list: - phantom.append(self.interop.get_device_details(device=i, query="phantom")) + phantom_states = [] + for device_eid in self.adb_device_list: + phantom_states.append(self.interop.get_device_details(device=device_eid, query="phantom")) if self.adb_device_list or self.windows_list or self.linux_list or self.mac_list: - for i in self.adb_device_list: - self.android_user_names.append(self.interop.get_device_details(device=i, query="user-name")) + for device_eid in self.adb_device_list: + self.android_user_names.append(self.interop.get_device_details(device=device_eid, query="user-name")) logging.info(f"ADB user-names for selected devices: {self.android_user_names}") logging.info("Checking heath data...") - health = dict.fromkeys(self.adb_device_list) - logging.info(f"Initial Health Data For Android Clients: {health}") - health_for_laptops = dict.fromkeys(self.all_laptops) - logging.info(f"Initial Health Data For Laptops Clients: {health_for_laptops}") + android_health = dict.fromkeys(self.adb_device_list) + logging.info(f"Initial Health Data For Android Clients: {android_health}") + laptop_health = dict.fromkeys(self.all_laptops) + logging.info(f"Initial Health Data For Laptops Clients: {laptop_health}") # pre-checking whether the adb device connected to given ssid or not - for i in self.adb_device_list: - dev_state = self.utility.get_device_state(device=i) - if dev_state == "COMPLETED,": - logging.info("Phone %s is in connected state." % i) - ssid = self.utility.get_device_ssid(device=i) - if ssid == self.ssid: - logging.info("The Device %s is connected to expected ssid (%s)" % (i, ssid)) - health[i] = self.utility.get_wifi_health_monitor(device=i, ssid=self.ssid) + for device_eid in self.adb_device_list: + device_state = self.utility.get_device_state(device=device_eid) + if device_state == "COMPLETED,": + logging.info("Phone %s is in connected state." % device_eid) + device_ssid = self.utility.get_device_ssid(device=device_eid) + if device_ssid == self.ssid: + logging.info("The Device %s is connected to expected ssid (%s)" % (device_eid, device_ssid)) + android_health[device_eid] = self.utility.get_wifi_health_monitor(device=device_eid, ssid=self.ssid) else: logging.info("**** The Device is not connected to the expected ssid ****") else: - # logging.info(f"Waiting for {self.wait_time} sec & Checking again the status of the device") logging.info("Waiting for 30 sec & Checking again") time.sleep(30) - dev_state = self.utility.get_device_state(device=i) - logging.info("Checking Device Status Again..." + str(dev_state)) - logging.info(f"Device state {dev_state}") - if dev_state == "COMPLETED,": + device_state = self.utility.get_device_state(device=device_eid) + logging.info("Checking Device Status Again..." + str(device_state)) + logging.info(f"Device state {device_state}") + if device_state == "COMPLETED,": logging.info("Phone is in connected state") - ssid = self.utility.get_device_ssid(device=i) - if ssid == self.ssid: - logging.info("The Device %s is connected to expected ssid (%s)" % (i, ssid)) - health[i] = self.utility.get_wifi_health_monitor(device=i, ssid=self.ssid) + device_ssid = self.utility.get_device_ssid(device=device_eid) + if device_ssid == self.ssid: + logging.info("The Device %s is connected to expected ssid (%s)" % (device_eid, device_ssid)) + android_health[device_eid] = self.utility.get_wifi_health_monitor(device=device_eid, ssid=self.ssid) else: - logging.info(f"device state {dev_state}") - health[i] = {'ConnectAttempt': '0', 'ConnectFailure': '0', 'AssocRej': '0', - 'AssocTimeout': '0'} - logging.info(f"Health Status for the Android Devices: {health}") + logging.info(f"device state {device_state}") + android_health[device_eid] = {'ConnectAttempt': '0', 'ConnectFailure': '0', 'AssocRej': '0', + 'AssocTimeout': '0'} + logging.info(f"Health Status for the Android Devices: {android_health}") - logging.info(f"Health Status for the Laptop Devices: {health_for_laptops}") + logging.info(f"Health Status for the Laptop Devices: {laptop_health}") # Resting Starts from here if not self.robot_test: - reset_dict, test_duration = self.performing_resets(test_start_time=test_start_time) - return reset_dict, test_duration + per_iteration_results, test_duration = self.performing_resets(test_start_time=test_start_time) + return per_iteration_results, test_duration # For robot Scenario if (self.rotation_list[0] != ""): @@ -954,38 +954,38 @@ def run(self): self.robot_obj.testname = self.test_name self.robot_obj.runtime_dir = self.result_dir test_stopped_by_user = False - for coordinate in range(len(self.coordinate_list)): + for coordinate_index in range(len(self.coordinate_list)): if test_stopped_by_user or self.robo_test_stopped: break # Check for battery status before moving to next coordinate - if_paused, test_stopped_by_user = self.robot_obj.wait_for_battery() + _, test_stopped_by_user = self.robot_obj.wait_for_battery() # If test is stopped by user during battery wait if test_stopped_by_user: break - robo_moved, abort = self.robot_obj.move_to_coordinate(self.coordinate_list[coordinate]) + reached_coordinate, abort = self.robot_obj.move_to_coordinate(self.coordinate_list[coordinate_index]) # If robot failed to reach the coordinate if abort: break - if robo_moved: - self.current_coordinate = self.coordinate_list[coordinate] + if reached_coordinate: + self.current_coordinate = self.coordinate_list[coordinate_index] if not self.rotation_enabled: - reset_dict, test_duration = self.performing_resets(test_start_time=test_start_time) - self.port_reset_data[self.coordinate_list[coordinate]] = {'reset_dict': reset_dict, 'test_duration': test_duration} + per_iteration_results, test_duration = self.performing_resets(test_start_time=test_start_time) + self.port_reset_data[self.coordinate_list[coordinate_index]] = {'reset_dict': per_iteration_results, 'test_duration': test_duration} time.sleep(10) else: - for angle in range(len(self.rotation_list)): + for angle_index in range(len(self.rotation_list)): # If test is stopped by user during battery wait if self.robo_test_stopped or test_stopped_by_user: break # Check for battery status before rotating to next angle - is_paused, test_stopped_by_user = self.robot_obj.wait_for_battery() - robo_rotated = self.robot_obj.rotate_angle(self.rotation_list[angle]) - if robo_rotated: - self.current_angle = self.rotation_list[angle] - reset_dict, test_duration = self.performing_resets(test_start_time=test_start_time) - if self.coordinate_list[coordinate] not in self.port_reset_data: - self.port_reset_data[self.coordinate_list[coordinate]] = {} - self.port_reset_data[self.coordinate_list[coordinate]][self.rotation_list[angle]] = {'reset_dict': reset_dict, 'test_duration': test_duration} + _, test_stopped_by_user = self.robot_obj.wait_for_battery() + rotated = self.robot_obj.rotate_angle(self.rotation_list[angle_index]) + if rotated: + self.current_angle = self.rotation_list[angle_index] + per_iteration_results, test_duration = self.performing_resets(test_start_time=test_start_time) + if self.coordinate_list[coordinate_index] not in self.port_reset_data: + self.port_reset_data[self.coordinate_list[coordinate_index]] = {} + self.port_reset_data[self.coordinate_list[coordinate_index]][self.rotation_list[angle_index]] = {'reset_dict': per_iteration_results, 'test_duration': test_duration} time.sleep(10) if test_stopped_by_user or self.robo_test_stopped: From 8728fe136e8a1770b0e9ee7fb3b80183f45ee0da Mon Sep 17 00:00:00 2001 From: Narayana-CT Date: Fri, 21 Aug 2026 12:53:51 +0530 Subject: [PATCH 04/13] lf_interop_port_reset_test.py: rename get_count(), get_time_from_wifi_msgs() and write_reset_csvs() Signed-off-by: Narayana-CT --- py-scripts/lf_interop_port_reset_test.py | 485 ++++++++++++----------- 1 file changed, 244 insertions(+), 241 deletions(-) diff --git a/py-scripts/lf_interop_port_reset_test.py b/py-scripts/lf_interop_port_reset_test.py index 5293adcd6..53a7cd142 100755 --- a/py-scripts/lf_interop_port_reset_test.py +++ b/py-scripts/lf_interop_port_reset_test.py @@ -287,209 +287,211 @@ def get_last_wifi_msg(self): logging.info(f"Last WiFi Message Time Stamp: {last}") return last - def get_count(self, value=None, keys_list=None, device=None, filter=None): - count_ = [] - device_split = device.split(".") - device = device_split[2] - resource_id = device_split[0] + "." + device_split[1] - for i, y in zip(keys_list, range(len(keys_list))): - wifi_msg_text = value[y][i]['text'] - resource = value[y][i]['resource'] + def count_wifi_msg_matches(self, wifi_messages=None, message_keys=None, device_eid=None, match_text=None): + matches = [] + eid_parts = device_eid.split(".") + port_name = eid_parts[2] + resource_id = eid_parts[0] + "." + eid_parts[1] + for message_key, index in zip(message_keys, range(len(message_keys))): + wifi_msg_text = wifi_messages[index][message_key]['text'] + message_resource = wifi_messages[index][message_key]['resource'] if type(wifi_msg_text) is str: - wifi_msg_text_keyword_list = value[y][i]['text'].split(" ") - if device is None: - logging.info(f"Device {device} is None device name not existed in wifi messages...") + message_tokens = wifi_messages[index][message_key]['text'].split(" ") + if port_name is None: + logging.info(f"Device {port_name} is None device name not existed in wifi messages...") else: - if resource == resource_id: - if device in wifi_msg_text_keyword_list: - if filter in wifi_msg_text_keyword_list: - # logging.info(f"The filter '{filter}' is present in the Wi-Fi message test list.") - count_.append("YES") + if message_resource == resource_id: + if port_name in message_tokens: + if match_text in message_tokens: + # logging.info(f"The filter '{match_text}' is present in the Wi-Fi message test list.") + matches.append("YES") else: - with_empty_filter = filter.split(" ") - if all(item in wifi_msg_text_keyword_list for item in with_empty_filter): - # logging.info(f"The filter {with_empty_filter} sequence is present in Wi-Fi msg.") - count_.append("YES") + match_tokens = match_text.split(" ") + if all(token in message_tokens for token in match_tokens): + # logging.info(f"The filter {match_tokens} sequence is present in Wi-Fi msg.") + matches.append("YES") else: - if f"IFNAME={device}" in wifi_msg_text_keyword_list: # for linux - if filter in wifi_msg_text_keyword_list: - # logging.info(f"The filter '{filter}' is present in the Wi-Fi message test list.") - count_.append("YES") + if f"IFNAME={port_name}" in message_tokens: # for linux + if match_text in message_tokens: + # logging.info(f"The filter '{match_text}' is present in the Wi-Fi message test list.") + matches.append("YES") else: - with_empty_filter = filter.split(" ") - if all(item in wifi_msg_text_keyword_list for item in with_empty_filter): - # logging.info(f"The filter {with_empty_filter} sequence is present in Wi-Fi msg.") - count_.append("YES") - else: # if wifi_msg_test is list - for item in wifi_msg_text: - wifi_msg_text_keyword_list = item.split(" ") - # print("$Wifi Message Text list:", wifi_msg_text_keyword_list) - if device is not None: - if resource == resource_id: - if device in wifi_msg_text_keyword_list: # for android - if filter in wifi_msg_text_keyword_list: - # logging.info(f"The filter '{filter}' is present in the Wi-Fi message test list.") - count_.append("YES") + match_tokens = match_text.split(" ") + if all(token in message_tokens for token in match_tokens): + # logging.info(f"The filter {match_tokens} sequence is present in Wi-Fi msg.") + matches.append("YES") + else: # if wifi_msg_text is list + for message_line in wifi_msg_text: + message_tokens = message_line.split(" ") + # print("$Wifi Message Text list:", message_tokens) + if port_name is not None: + if message_resource == resource_id: + if port_name in message_tokens: # for android + if match_text in message_tokens: + # logging.info(f"The filter '{match_text}' is present in the Wi-Fi message test list.") + matches.append("YES") else: - with_empty_filter = filter.split(" ") - if all(item in wifi_msg_text_keyword_list for item in with_empty_filter): - # logging.info(f"The filter {with_empty_filter} sequence is present in Wi-Fi msg.") - count_.append("YES") + match_tokens = match_text.split(" ") + if all(token in message_tokens for token in match_tokens): + # logging.info(f"The filter {match_tokens} sequence is present in Wi-Fi msg.") + matches.append("YES") else: - if f"IFNAME={device}" in wifi_msg_text_keyword_list: # for linux - if filter in wifi_msg_text_keyword_list: - # logging.info(f"The filter '{filter}' is present in the Wi-Fi message test list.") - count_.append("YES") + if f"IFNAME={port_name}" in message_tokens: # for linux + if match_text in message_tokens: + # logging.info(f"The filter '{match_text}' is present in the Wi-Fi message test list.") + matches.append("YES") else: - with_empty_filter = filter.split(" ") - if all(item in wifi_msg_text_keyword_list for item in with_empty_filter): - # logging.info(f"The filter {with_empty_filter} sequence is present in Wi-Fi msg.") - count_.append("YES") - counting = count_.count("YES") - return counting - - def get_time_from_wifi_msgs(self, local_dict=None, phn_name=None, timee=None, file_name="dummy.json", reset_cnt=None): + match_tokens = match_text.split(" ") + if all(token in message_tokens for token in match_tokens): + # logging.info(f"The filter {match_tokens} sequence is present in Wi-Fi msg.") + matches.append("YES") + match_count = matches.count("YES") + return match_count + + def collect_device_metrics(self, device_metrics=None, device_eid=None, since_time=None, file_name="dummy.json", iteration=None): # print("Waiting for 20 sec to fetch the logs...") # time.sleep(20) - a = self.json_get_with_retry("/wifi-msgs/since=time/" + str(timee), debug_=True) + wifi_msgs_response = self.json_get_with_retry("/wifi-msgs/since=time/" + str(since_time), debug_=True) try: - values = a['wifi-messages'] + wifi_messages = wifi_msgs_response['wifi-messages'] except (TypeError, KeyError) as e: logging.error( - f"get_time_from_wifi_msgs: LANforge response is not in expected format ({e}) while fetching " - f"wifi-msgs for device {phn_name}. Data received: {a}") - logging.warning(f"Defaulting device {phn_name} stats to 0 for this reset and continuing.") - for key in ("ConnectAttempt", "Disconnected", "Scanning", "Association Rejection", "Connected"): - local_dict[str(phn_name)][key] = 0 - local_dict[str(phn_name)]["Remarks"] = "Data unavailable - LANforge API error, stats defaulted to 0" - local_dict[str(phn_name)]["cx time (us)"] = "NA" - self.write_reset_csvs(local_dict, reset_cnt) - return local_dict - # print("Wifi msgs Response : ", values) + f"collect_device_metrics: LANforge response is not in expected format ({e}) while fetching " + f"wifi-msgs for device {device_eid}. Data received: {wifi_msgs_response}") + logging.warning(f"Defaulting device {device_eid} stats to 0 for this reset and continuing.") + for metric_name in ("ConnectAttempt", "Disconnected", "Scanning", "Association Rejection", "Connected"): + device_metrics[str(device_eid)][metric_name] = 0 + device_metrics[str(device_eid)]["Remarks"] = "Data unavailable - LANforge API error, stats defaulted to 0" + device_metrics[str(device_eid)]["cx time (us)"] = "NA" + self.write_iteration_csvs(device_metrics, iteration) + return device_metrics + # print("Wifi msgs Response : ", wifi_messages) logging.info( - f"Counting the DISCONNECTIONS, SCANNING, ASSOC ATTEMPTS, ASSOC RECJECTIONS, CONNECTS for device {phn_name}") - if type(values) is not list: - logging.info(f"Device {phn_name} : Getting wifi messages for only single time-stamp. Converting into List.") - values = [{f"{values['resource']}.{values['time-stamp']}": values}] - # print("After Updating Wi-Fi msgs Response : ", values) - self.create_log_file(json_list=values, file_name=file_name) + f"Counting the DISCONNECTIONS, SCANNING, ASSOC ATTEMPTS, ASSOC RECJECTIONS, CONNECTS for device {device_eid}") + if type(wifi_messages) is not list: + logging.info(f"Device {device_eid} : Getting wifi messages for only single time-stamp. Converting into List.") + wifi_messages = [{f"{wifi_messages['resource']}.{wifi_messages['time-stamp']}": wifi_messages}] + # print("After Updating Wi-Fi msgs Response : ", wifi_messages) + self.create_log_file(json_list=wifi_messages, file_name=file_name) self.remove_files_with_duplicate_names(folder_path=f"{self.report_path}/Wifi_Messages/") - keys_list = [] + message_keys = [] - for i in range(len(values)): - keys_list.append(list(values[i].keys())[0]) - # print("Key list", keys_list) + for index in range(len(wifi_messages)): + message_keys.append(list(wifi_messages[index].keys())[0]) + # print("Key list", message_keys) # android (flag) check for clustered lanforge cases - android = False + is_android = False adb_response = self.json_get_with_retry('/adb/') try: adb_devices = adb_response['devices'] except (TypeError, KeyError) as e: logging.error( - f"get_time_from_wifi_msgs: LANforge response is not in expected format ({e}) while fetching " + f"collect_device_metrics: LANforge response is not in expected format ({e}) while fetching " f"/adb/ devices. Data received: {adb_response}") logging.warning( - f"Could not fetch adb device list; relying only on the '1.1.' prefix heuristic for {phn_name}.") + f"Could not fetch adb device list; relying only on the '1.1.' prefix heuristic for {device_eid}.") adb_devices = [] for device_data in adb_devices: device_name, _ = list(device_data.keys())[0], list(device_data.values())[0] - if phn_name in device_name: - android = True + if device_eid in device_name: + is_android = True break - if "1.1." in phn_name or android: + if "1.1." in device_eid or is_android: # disconnects - adb_disconnect_count = self.get_count(value=values, keys_list=keys_list, device=phn_name, - filter="Terminating...") # Todo: need to rename the method - if adb_disconnect_count > 1 or adb_disconnect_count == 0: - disconnection = self.utility.get_device_state(device=phn_name) - if disconnection == 'COMPLETED': - logging.info("The Device %s is in connected state." % phn_name) - adb_disconnect_count = 0 + android_disconnect_count = self.count_wifi_msg_matches(wifi_messages=wifi_messages, message_keys=message_keys, + device_eid=device_eid, match_text="Terminating...") + if android_disconnect_count > 1 or android_disconnect_count == 0: + device_state = self.utility.get_device_state(device=device_eid) + if device_state == 'COMPLETED': + logging.info("The Device %s is in connected state." % device_eid) + android_disconnect_count = 0 else: - logging.info("The Device %s is not in connected state." % phn_name) - adb_disconnect_count = 1 - logging.info(f"Disconnect Count For Android: {adb_disconnect_count}") + logging.info("The Device %s is not in connected state." % device_eid) + android_disconnect_count = 1 + logging.info(f"Disconnect Count For Android: {android_disconnect_count}") # Updating the dict with disconnects for android - logging.info("Final Disconnect count for %s: %s" % (phn_name, adb_disconnect_count)) - local_dict[phn_name]["Disconnected"] = adb_disconnect_count + logging.info("Final Disconnect count for %s: %s" % (device_eid, android_disconnect_count)) + device_metrics[device_eid]["Disconnected"] = android_disconnect_count # scanning count - adb_scan_count = self.get_count(value=values, keys_list=keys_list, device=phn_name, filter="SCAN-STARTED") - logging.info("Final Scanning Count for %s: %s" % (phn_name, adb_scan_count)) - local_dict[str(phn_name)]["Scanning"] = adb_scan_count + android_scan_count = self.count_wifi_msg_matches(wifi_messages=wifi_messages, message_keys=message_keys, + device_eid=device_eid, match_text="SCAN-STARTED") + logging.info("Final Scanning Count for %s: %s" % (device_eid, android_scan_count)) + device_metrics[str(device_eid)]["Scanning"] = android_scan_count # association attempts - adb_association_attempt = self.get_count(value=values, keys_list=keys_list, device=phn_name, - filter="ASSOCIATING") - logging.info("Final Association Attempts Count for %s: %s" % (phn_name, adb_association_attempt)) - local_dict[str(phn_name)]["ConnectAttempt"] = adb_association_attempt + android_association_attempt = self.count_wifi_msg_matches(wifi_messages=wifi_messages, message_keys=message_keys, + device_eid=device_eid, match_text="ASSOCIATING") + logging.info("Final Association Attempts Count for %s: %s" % (device_eid, android_association_attempt)) + device_metrics[str(device_eid)]["ConnectAttempt"] = android_association_attempt # association rejections - adb_association_rejection = self.get_count(value=values, keys_list=keys_list, device=phn_name, - filter="ASSOC_REJECT") - logging.info("Final Association Rejection Count for %s: %s" % (phn_name, adb_association_rejection)) - local_dict[str(phn_name)]["Association Rejection"] = adb_association_rejection + android_association_rejection = self.count_wifi_msg_matches(wifi_messages=wifi_messages, message_keys=message_keys, + device_eid=device_eid, match_text="ASSOC_REJECT") + logging.info("Final Association Rejection Count for %s: %s" % (device_eid, android_association_rejection)) + device_metrics[str(device_eid)]["Association Rejection"] = android_association_rejection # connections - adb_connected_count = self.get_count(value=values, keys_list=keys_list, device=phn_name, - filter="CTRL-EVENT-CONNECTED") + android_connected_count = self.count_wifi_msg_matches(wifi_messages=wifi_messages, message_keys=message_keys, + device_eid=device_eid, match_text="CTRL-EVENT-CONNECTED") # Double-checking & adding remarks if any - if adb_connected_count > 1 or adb_connected_count == 0: - ssid = self.utility.get_device_ssid(device=phn_name) - if ssid == self.ssid: - logging.info("The Device %s is connected to expected ssid" % phn_name) - adb_connected_count = 1 + if android_connected_count > 1 or android_connected_count == 0: + device_ssid = self.utility.get_device_ssid(device=device_eid) + if device_ssid == self.ssid: + logging.info("The Device %s is connected to expected ssid" % device_eid) + android_connected_count = 1 else: logging.info("**** The Device is not connected to the expected ssid ****") - adb_connected_count = 0 - logging.info(f"Connected Count for Android: {adb_connected_count}") + android_connected_count = 0 + logging.info(f"Connected Count for Android: {android_connected_count}") # Updating the dict with connects for android - logging.info("Final Connected Count for %s: %s" % (phn_name, adb_connected_count)) - local_dict[str(phn_name)]["Connected"] = adb_connected_count + logging.info("Final Connected Count for %s: %s" % (device_eid, android_connected_count)) + device_metrics[str(device_eid)]["Connected"] = android_connected_count # Adding remarks remarks = "NA" - local_dict[str(phn_name)]["Remarks"] = remarks + device_metrics[str(device_eid)]["Remarks"] = remarks # Updating the association-rejections - if adb_association_attempt > adb_connected_count: - adb_association_rejection = adb_association_attempt - adb_connected_count - local_dict[str(phn_name)]["Association Rejection"] = adb_association_rejection - if adb_connected_count > 0: - _, shelf, serial = phn_name.split('.') - resource_id_resp = self.json_get_with_retry('/adb/1/{}/{}?fields=resource-id'.format(shelf, serial)) - port_ssid_query = None + if android_association_attempt > android_connected_count: + android_association_rejection = android_association_attempt - android_connected_count + device_metrics[str(device_eid)]["Association Rejection"] = android_association_rejection + if android_connected_count > 0: + _, resource, serial = device_eid.split('.') + resource_id_response = self.json_get_with_retry('/adb/1/{}/{}?fields=resource-id'.format(resource, serial)) + port_response = None try: - resource_id = resource_id_resp['devices']['resource-id'] - port_ssid_query = self.json_get_with_retry('port/1/{}/wlan0?fields=cx time (us)'.format(resource_id.split('.')[1])) - uptime = port_ssid_query['interface']['cx time (us)'] - local_dict[str(phn_name)]['cx time (us)'] = uptime + resource_id = resource_id_response['devices']['resource-id'] + port_response = self.json_get_with_retry('port/1/{}/wlan0?fields=cx time (us)'.format(resource_id.split('.')[1])) + cx_time_us = port_response['interface']['cx time (us)'] + device_metrics[str(device_eid)]['cx time (us)'] = cx_time_us except (TypeError, KeyError) as e: logging.error( - f"get_time_from_wifi_msgs: could not fetch cx time (us) for device {phn_name}; LANforge " - f"response is not in expected format ({e}). resource-id response: {resource_id_resp}, " - f"port response: {port_ssid_query}") - local_dict[str(phn_name)]['cx time (us)'] = 'NA' + f"collect_device_metrics: could not fetch cx time (us) for device {device_eid}; LANforge " + f"response is not in expected format ({e}). resource-id response: {resource_id_response}, " + f"port response: {port_response}") + device_metrics[str(device_eid)]['cx time (us)'] = 'NA' else: - local_dict[str(phn_name)]['cx time (us)'] = 'NA' + device_metrics[str(device_eid)]['cx time (us)'] = 'NA' else: - if phn_name in self.windows_list: # for windows - win_disconnect_count = self.get_count(value=values, keys_list=keys_list, device=phn_name, - filter="Wireless security stopped.") + if device_eid in self.windows_list: # for windows + win_disconnect_count = self.count_wifi_msg_matches(wifi_messages=wifi_messages, message_keys=message_keys, + device_eid=device_eid, match_text="Wireless security stopped.") # Double-checking the disconnect count with another key msg if win_disconnect_count == 0: - win_disconnect_count = self.get_count(value=values, keys_list=keys_list, device=phn_name, - filter="WLAN AutoConfig service has successfully disconnected from a wireless network") - logging.info("Final Disconnect count for %s: %s" % (phn_name, win_disconnect_count)) - local_dict[phn_name]["Disconnected"] = win_disconnect_count - win_scan_count = self.get_count(value=values, keys_list=keys_list, device=phn_name, - filter="service started") - logging.info("Final Scanning Count for %s: %s" % (phn_name, win_scan_count)) - local_dict[str(phn_name)]["Scanning"] = win_scan_count - win_association_attempt = self.get_count(value=values, keys_list=keys_list, device=phn_name, - filter="association started.") - logging.info("Final Association Attempts Count for %s: %s" % (phn_name, win_association_attempt)) - local_dict[str(phn_name)]["ConnectAttempt"] = win_association_attempt - win_association_rejection = self.get_count(value=values, keys_list=keys_list, device=phn_name, - filter="failed to connect") - logging.info("Final Association Rejection Count for %s: %s" % (phn_name, win_association_rejection)) - local_dict[str(phn_name)]["Association Rejection"] = win_association_rejection - win_connected_count = self.get_count(value=values, keys_list=keys_list, device=phn_name, - filter="connected") + win_disconnect_count = self.count_wifi_msg_matches(wifi_messages=wifi_messages, message_keys=message_keys, + device_eid=device_eid, + match_text="WLAN AutoConfig service has successfully disconnected from a wireless network") + logging.info("Final Disconnect count for %s: %s" % (device_eid, win_disconnect_count)) + device_metrics[device_eid]["Disconnected"] = win_disconnect_count + win_scan_count = self.count_wifi_msg_matches(wifi_messages=wifi_messages, message_keys=message_keys, + device_eid=device_eid, match_text="service started") + logging.info("Final Scanning Count for %s: %s" % (device_eid, win_scan_count)) + device_metrics[str(device_eid)]["Scanning"] = win_scan_count + win_association_attempt = self.count_wifi_msg_matches(wifi_messages=wifi_messages, message_keys=message_keys, + device_eid=device_eid, match_text="association started.") + logging.info("Final Association Attempts Count for %s: %s" % (device_eid, win_association_attempt)) + device_metrics[str(device_eid)]["ConnectAttempt"] = win_association_attempt + win_association_rejection = self.count_wifi_msg_matches(wifi_messages=wifi_messages, message_keys=message_keys, + device_eid=device_eid, match_text="failed to connect") + logging.info("Final Association Rejection Count for %s: %s" % (device_eid, win_association_rejection)) + device_metrics[str(device_eid)]["Association Rejection"] = win_association_rejection + win_connected_count = self.count_wifi_msg_matches(wifi_messages=wifi_messages, message_keys=message_keys, + device_eid=device_eid, match_text="connected") win_connection_state_unverified = False # assoc-rejection based logic if win_association_rejection: @@ -505,26 +507,26 @@ def get_time_from_wifi_msgs(self, local_dict=None, phn_name=None, timee=None, fi else: # Double-checking if win_connected_count > 1 or win_connected_count == 0: - port_name = phn_name.split(".") - port_ssid_query = self.json_get_with_retry(f"port/{port_name[0]}/{port_name[1]}/{port_name[2]}?fields=ssid,ip") + eid_parts = device_eid.split(".") + port_response = self.json_get_with_retry(f"port/{eid_parts[0]}/{eid_parts[1]}/{eid_parts[2]}?fields=ssid,ip") try: - if port_ssid_query['interface']['ssid'] == self.ssid and port_ssid_query['interface']['ip'] != "0.0.0.0": + if port_response['interface']['ssid'] == self.ssid and port_response['interface']['ip'] != "0.0.0.0": win_connected_count = 1 else: win_connected_count = 0 except (TypeError, KeyError) as e: logging.error( - f"get_time_from_wifi_msgs: could not verify connection state for device " - f"{phn_name}; LANforge response is not in expected format ({e}). Data " - f"received: {port_ssid_query}") + f"collect_device_metrics: could not verify connection state for device " + f"{device_eid}; LANforge response is not in expected format ({e}). Data " + f"received: {port_response}") win_connected_count = 0 win_connection_state_unverified = True - logging.info("Final Connected Count for %s: %s" % (phn_name, win_connected_count)) - local_dict[str(phn_name)]["Connected"] = win_connected_count + logging.info("Final Connected Count for %s: %s" % (device_eid, win_connected_count)) + device_metrics[str(device_eid)]["Connected"] = win_connected_count # Updating the association-rejections if win_association_attempt > win_connected_count: win_association_rejection = win_association_attempt - win_connected_count - local_dict[str(phn_name)]["Association Rejection"] = win_association_rejection + device_metrics[str(device_eid)]["Association Rejection"] = win_association_rejection # Adding re-marks remarks = "NA" if win_disconnect_count == 0 and win_connected_count == 1: @@ -533,111 +535,112 @@ def get_time_from_wifi_msgs(self, local_dict=None, phn_name=None, timee=None, fi remarks = "The Disconnections are seen but Client did not connected to user given SSID." if win_connection_state_unverified: remarks = "Connection state unverified - LANforge API error while double-checking connect count" - local_dict[str(phn_name)]["Remarks"] = remarks + device_metrics[str(device_eid)]["Remarks"] = remarks if win_connected_count > 0: - port_name = phn_name.split(".") - port_ssid_query = self.json_get_with_retry(f"port/{port_name[0]}/{port_name[1]}/{port_name[2]}?fields=cx time (us)") + eid_parts = device_eid.split(".") + port_response = self.json_get_with_retry(f"port/{eid_parts[0]}/{eid_parts[1]}/{eid_parts[2]}?fields=cx time (us)") try: - uptime = port_ssid_query['interface']['cx time (us)'] - local_dict[str(phn_name)]['cx time (us)'] = uptime + cx_time_us = port_response['interface']['cx time (us)'] + device_metrics[str(device_eid)]['cx time (us)'] = cx_time_us except (TypeError, KeyError) as e: logging.error( - f"get_time_from_wifi_msgs: could not fetch cx time (us) for device {phn_name}; " - f"LANforge response is not in expected format ({e}). Data received: {port_ssid_query}") - local_dict[str(phn_name)]['cx time (us)'] = 'NA' + f"collect_device_metrics: could not fetch cx time (us) for device {device_eid}; " + f"LANforge response is not in expected format ({e}). Data received: {port_response}") + device_metrics[str(device_eid)]['cx time (us)'] = 'NA' else: - local_dict[str(phn_name)]['cx time (us)'] = 'NA' + device_metrics[str(device_eid)]['cx time (us)'] = 'NA' else: # other means (for linux, mac) - other_disconnect_count = self.get_count(value=values, keys_list=keys_list, device=phn_name, - filter="disconnected") + linux_mac_disconnect_count = self.count_wifi_msg_matches(wifi_messages=wifi_messages, message_keys=message_keys, + device_eid=device_eid, match_text="disconnected") # Double-checking the disconnect count with another key msg - if other_disconnect_count == 0: - other_disconnect_count = self.get_count(value=values, keys_list=keys_list, device=phn_name, - filter="<3>CTRL-EVENT-DSCP-POLICY clear_all") - logging.info("Final Disconnect count for %s: %s" % (phn_name, other_disconnect_count)) - local_dict[phn_name]["Disconnected"] = other_disconnect_count - other_scan_count = self.get_count(value=values, keys_list=keys_list, device=phn_name, - filter="<3>CTRL-EVENT-SCAN-STARTED") - logging.info("Final Scanning Count for %s: %s" % (phn_name, other_scan_count)) - local_dict[str(phn_name)]["Scanning"] = other_scan_count - other_association_attempt = self.get_count(value=values, keys_list=keys_list, device=phn_name, - filter="<3>Trying to associate with") - logging.info("Final Association Attempts Count for %s: %s" % (phn_name, other_association_attempt)) - local_dict[str(phn_name)]["ConnectAttempt"] = other_association_attempt - other_association_rejection = self.get_count(value=values, keys_list=keys_list, device=phn_name, - filter="NoneValue") - logging.info("Final Association Rejection Count for %s: %s" % (phn_name, other_association_rejection)) - local_dict[str(phn_name)]["Association Rejection"] = other_association_rejection - - other_connected_count = self.get_count(value=values, keys_list=keys_list, device=phn_name, - filter="<3>CTRL-EVENT-CONNECTED") - other_connection_state_unverified = False + if linux_mac_disconnect_count == 0: + linux_mac_disconnect_count = self.count_wifi_msg_matches(wifi_messages=wifi_messages, message_keys=message_keys, + device_eid=device_eid, + match_text="<3>CTRL-EVENT-DSCP-POLICY clear_all") + logging.info("Final Disconnect count for %s: %s" % (device_eid, linux_mac_disconnect_count)) + device_metrics[device_eid]["Disconnected"] = linux_mac_disconnect_count + linux_mac_scan_count = self.count_wifi_msg_matches(wifi_messages=wifi_messages, message_keys=message_keys, + device_eid=device_eid, match_text="<3>CTRL-EVENT-SCAN-STARTED") + logging.info("Final Scanning Count for %s: %s" % (device_eid, linux_mac_scan_count)) + device_metrics[str(device_eid)]["Scanning"] = linux_mac_scan_count + linux_mac_association_attempt = self.count_wifi_msg_matches(wifi_messages=wifi_messages, message_keys=message_keys, + device_eid=device_eid, match_text="<3>Trying to associate with") + logging.info("Final Association Attempts Count for %s: %s" % (device_eid, linux_mac_association_attempt)) + device_metrics[str(device_eid)]["ConnectAttempt"] = linux_mac_association_attempt + linux_mac_association_rejection = self.count_wifi_msg_matches(wifi_messages=wifi_messages, message_keys=message_keys, + device_eid=device_eid, match_text="NoneValue") + logging.info("Final Association Rejection Count for %s: %s" % (device_eid, linux_mac_association_rejection)) + device_metrics[str(device_eid)]["Association Rejection"] = linux_mac_association_rejection + + linux_mac_connected_count = self.count_wifi_msg_matches(wifi_messages=wifi_messages, message_keys=message_keys, + device_eid=device_eid, match_text="<3>CTRL-EVENT-CONNECTED") + linux_mac_connection_state_unverified = False # assoc-rejection based logic - if other_association_rejection: + if linux_mac_association_rejection: # Updating the connects - actual_connects = other_association_attempt - other_association_rejection - if actual_connects == other_connected_count: - other_connected_count = other_connected_count + actual_connects = linux_mac_association_attempt - linux_mac_association_rejection + if actual_connects == linux_mac_connected_count: + linux_mac_connected_count = linux_mac_connected_count else: - other_connected_count = actual_connects + linux_mac_connected_count = actual_connects else: - if other_association_attempt == other_connected_count: - other_connected_count = other_connected_count + if linux_mac_association_attempt == linux_mac_connected_count: + linux_mac_connected_count = linux_mac_connected_count else: # Double-checking & adding remarks if any - if other_connected_count > 1 or other_connected_count == 0: - port_name = phn_name.split(".") - port_ssid_query = self.json_get_with_retry(f"port/{port_name[0]}/{port_name[1]}/{port_name[2]}?fields=ssid,ip") + if linux_mac_connected_count > 1 or linux_mac_connected_count == 0: + eid_parts = device_eid.split(".") + port_response = self.json_get_with_retry(f"port/{eid_parts[0]}/{eid_parts[1]}/{eid_parts[2]}?fields=ssid,ip") try: - if port_ssid_query['interface']['ssid'] == self.ssid and port_ssid_query['interface']['ip'] != "0.0.0.0": - other_connected_count = 1 + if port_response['interface']['ssid'] == self.ssid and port_response['interface']['ip'] != "0.0.0.0": + linux_mac_connected_count = 1 else: - other_connected_count = 0 + linux_mac_connected_count = 0 except (TypeError, KeyError) as e: logging.error( - f"get_time_from_wifi_msgs: could not verify connection state for device " - f"{phn_name}; LANforge response is not in expected format ({e}). Data " - f"received: {port_ssid_query}") - other_connected_count = 0 - other_connection_state_unverified = True - logging.info("Final Connected Count for %s: %s" % (phn_name, other_connected_count)) - local_dict[str(phn_name)]["Connected"] = other_connected_count + f"collect_device_metrics: could not verify connection state for device " + f"{device_eid}; LANforge response is not in expected format ({e}). Data " + f"received: {port_response}") + linux_mac_connected_count = 0 + linux_mac_connection_state_unverified = True + logging.info("Final Connected Count for %s: %s" % (device_eid, linux_mac_connected_count)) + device_metrics[str(device_eid)]["Connected"] = linux_mac_connected_count # Updating the association-rejections - if other_association_attempt > other_connected_count: - other_association_rejection = other_association_attempt - other_connected_count - local_dict[str(phn_name)]["Association Rejection"] = other_association_rejection + if linux_mac_association_attempt > linux_mac_connected_count: + linux_mac_association_rejection = linux_mac_association_attempt - linux_mac_connected_count + device_metrics[str(device_eid)]["Association Rejection"] = linux_mac_association_rejection # Adding remarks remarks = "NA" - if other_disconnect_count == 0 and other_connected_count == 1: + if linux_mac_disconnect_count == 0 and linux_mac_connected_count == 1: remarks = "No Disconnections are seen but Client is UP and connected to user given SSID." - elif other_disconnect_count >= 1 and other_connected_count == 0: + elif linux_mac_disconnect_count >= 1 and linux_mac_connected_count == 0: remarks = "The Disconnections are seen but Client did not connected to user given SSID." - if other_connection_state_unverified: + if linux_mac_connection_state_unverified: remarks = "Connection state unverified - LANforge API error while double-checking connect count" - local_dict[str(phn_name)]["Remarks"] = remarks - if other_connected_count > 0: - port_name = phn_name.split(".") - port_ssid_query = self.json_get_with_retry(f"port/{port_name[0]}/{port_name[1]}/{port_name[2]}?fields=cx time (us)") + device_metrics[str(device_eid)]["Remarks"] = remarks + if linux_mac_connected_count > 0: + eid_parts = device_eid.split(".") + port_response = self.json_get_with_retry(f"port/{eid_parts[0]}/{eid_parts[1]}/{eid_parts[2]}?fields=cx time (us)") try: - uptime = port_ssid_query['interface']['cx time (us)'] - local_dict[str(phn_name)]['cx time (us)'] = uptime + cx_time_us = port_response['interface']['cx time (us)'] + device_metrics[str(device_eid)]['cx time (us)'] = cx_time_us except (TypeError, KeyError) as e: logging.error( - f"get_time_from_wifi_msgs: could not fetch cx time (us) for device {phn_name}; " - f"LANforge response is not in expected format ({e}). Data received: {port_ssid_query}") - local_dict[str(phn_name)]['cx time (us)'] = 'NA' + f"collect_device_metrics: could not fetch cx time (us) for device {device_eid}; " + f"LANforge response is not in expected format ({e}). Data received: {port_response}") + device_metrics[str(device_eid)]['cx time (us)'] = 'NA' else: - local_dict[str(phn_name)]['cx time (us)'] = 'NA' - logging.info("local_dict " + str(local_dict)) - self.write_reset_csvs(local_dict, reset_cnt) + device_metrics[str(device_eid)]['cx time (us)'] = 'NA' + logging.info("device_metrics " + str(device_metrics)) + self.write_iteration_csvs(device_metrics, iteration) - return local_dict + return device_metrics - def write_reset_csvs(self, local_dict, reset_cnt): + def write_iteration_csvs(self, device_metrics, iteration): # storing results in csv file for each reset - for interface_name, metrics in local_dict.items(): + for device_eid, metrics in device_metrics.items(): df = pd.DataFrame([metrics]) - filename = f"{self.report_path}/{interface_name}_{reset_cnt}.csv" + filename = f"{self.report_path}/{device_eid}_{iteration}.csv" df.to_csv(filename, index=False) def aggregate_reset_dict(self, reset_dict): @@ -791,10 +794,10 @@ def performing_resets(self, test_start_time=None): logging.info("FAILED : MAY BE NOT ALL STATIONS ACQUIRED IP'S") time.sleep(30) for device_eid in self.all_selected_devices: - iteration_metrics = self.get_time_from_wifi_msgs(local_dict=device_metrics, phn_name=device_eid, - timee=since_time, - file_name=f"reset_{iteration}_log.json", - reset_cnt=iteration) + iteration_metrics = self.collect_device_metrics(device_metrics=device_metrics, device_eid=device_eid, + since_time=since_time, + file_name=f"reset_{iteration}_log.json", + iteration=iteration) per_iteration_results[iteration] = iteration_metrics if self.robot_test: self.generate_coordinate_csv(reset_dict=per_iteration_results, r=iteration) From d8f9543421e80488b3fc89410cd5dfe326db03fa Mon Sep 17 00:00:00 2001 From: Narayana-CT Date: Fri, 21 Aug 2026 13:02:28 +0530 Subject: [PATCH 05/13] "lf_interop_port_reset_test.py: rename aggregate_reset_dict(), generate_coordinate_csv() and create_dict_csv()" Signed-off-by: Narayana-CT --- py-scripts/lf_interop_port_reset_test.py | 116 +++++++++++------------ 1 file changed, 58 insertions(+), 58 deletions(-) diff --git a/py-scripts/lf_interop_port_reset_test.py b/py-scripts/lf_interop_port_reset_test.py index 53a7cd142..869df6bcb 100755 --- a/py-scripts/lf_interop_port_reset_test.py +++ b/py-scripts/lf_interop_port_reset_test.py @@ -643,62 +643,62 @@ def write_iteration_csvs(self, device_metrics, iteration): filename = f"{self.report_path}/{device_eid}_{iteration}.csv" df.to_csv(filename, index=False) - def aggregate_reset_dict(self, reset_dict): - aggregated = {} - for reset_id in sorted(reset_dict.keys()): - if reset_dict[reset_id] is None: + def aggregate_device_metrics(self, per_iteration_results): + aggregated_metrics = {} + for iteration in sorted(per_iteration_results.keys()): + if per_iteration_results[iteration] is None: continue - devices = reset_dict[reset_id] - for device, stats in devices.items(): - if device not in aggregated: - aggregated[device] = {} - for key, value in stats.items(): - if key in ("Remarks", "cx time (us)"): - aggregated[device][key] = value + iteration_metrics = per_iteration_results[iteration] + for device_eid, metrics in iteration_metrics.items(): + if device_eid not in aggregated_metrics: + aggregated_metrics[device_eid] = {} + for metric_name, value in metrics.items(): + if metric_name in ("Remarks", "cx time (us)"): + aggregated_metrics[device_eid][metric_name] = value else: - if key not in aggregated[device]: - aggregated[device][key] = 0 - aggregated[device][key] += int(value) if str(value).isdigit() else 0 - return dict(aggregated) + if metric_name not in aggregated_metrics[device_eid]: + aggregated_metrics[device_eid][metric_name] = 0 + aggregated_metrics[device_eid][metric_name] += int(value) if str(value).isdigit() else 0 + return dict(aggregated_metrics) - def generate_coordinate_csv(self, reset_dict, r): - cols = ['Client', 'ConnectAttempt', 'Disconnected', 'Scanning', 'Association Rejection', 'Connected', 'Iterations', 'Status', 'coordinate'] + def write_coordinate_csv(self, per_iteration_results, iteration): + columns = ['Client', 'ConnectAttempt', 'Disconnected', 'Scanning', 'Association Rejection', 'Connected', 'Iterations', 'Status', 'coordinate'] if self.rotation_enabled: - cols.append('angle') + columns.append('angle') if self.rotation_enabled: - suffix = f"_{self.current_coordinate}_{self.current_angle}" + client_suffix = f"_{self.current_coordinate}_{self.current_angle}" else: - suffix = f"_{self.current_coordinate}" - aggregated_dict = self.aggregate_reset_dict(reset_dict=reset_dict) + client_suffix = f"_{self.current_coordinate}" + aggregated_metrics = self.aggregate_device_metrics(per_iteration_results=per_iteration_results) if self.current_coordinate not in self.coordinate_df: self.coordinate_df[self.current_coordinate] = {} - df = pd.DataFrame(columns=cols) - for client, stats in aggregated_dict.items(): - client_name = f"{client}{suffix}" - self.coordinate_df[self.current_coordinate][client_name] = stats.copy() + df = pd.DataFrame(columns=columns) + for device_eid, metrics in aggregated_metrics.items(): + client_name = f"{device_eid}{client_suffix}" + self.coordinate_df[self.current_coordinate][client_name] = metrics.copy() self.coordinate_df[self.current_coordinate][client_name]["coordinate"] = self.current_coordinate self.coordinate_df[self.current_coordinate][client_name]["Status"] = "running" if self.rotation_enabled: self.coordinate_df[self.current_coordinate][client_name]["angle"] = self.current_angle rows = [] - for client, stats in self.coordinate_df[self.current_coordinate].items(): + for client_name, metrics in self.coordinate_df[self.current_coordinate].items(): row = { - 'Client': client, - 'ConnectAttempt': stats.get('ConnectAttempt', 0), - 'Disconnected': stats.get('Disconnected', 0), - 'Scanning': stats.get('Scanning', 0), - 'Association Rejection': stats.get('Association Rejection', 0), - 'Connected': stats.get('Connected', 0), - 'Iterations': r + 1, - 'Status': stats.get('Status', 'NA'), - 'coordinate': stats.get('coordinate', 'NA') + 'Client': client_name, + 'ConnectAttempt': metrics.get('ConnectAttempt', 0), + 'Disconnected': metrics.get('Disconnected', 0), + 'Scanning': metrics.get('Scanning', 0), + 'Association Rejection': metrics.get('Association Rejection', 0), + 'Connected': metrics.get('Connected', 0), + 'Iterations': iteration + 1, + 'Status': metrics.get('Status', 'NA'), + 'coordinate': metrics.get('coordinate', 'NA') } if self.rotation_enabled: - row['angle'] = stats.get('angle', 'NA') + row['angle'] = metrics.get('angle', 'NA') rows.append(row) - df = pd.DataFrame(rows, columns=cols) + df = pd.DataFrame(rows, columns=columns) self.result_df = df.copy() df.to_csv(f"{self.report_path}/overall_reset_{self.current_coordinate}.csv", index=False) @@ -800,9 +800,9 @@ def performing_resets(self, test_start_time=None): iteration=iteration) per_iteration_results[iteration] = iteration_metrics if self.robot_test: - self.generate_coordinate_csv(reset_dict=per_iteration_results, r=iteration) + self.write_coordinate_csv(per_iteration_results=per_iteration_results, iteration=iteration) else: - self.create_dict_csv(per_iteration_results) + self.write_overall_csv(per_iteration_results) if self.dowebgui: with open(self.result_dir + f"/../../Running_instances/{self.lanforge_ip}_{self.test_name}_running.json", 'r') as file: @@ -1661,18 +1661,18 @@ def generate_report_for_robo(self): else: self.lf_report.write_pdf_with_timestamp(_page_size='A4', _orientation='Portrait') - def create_dict_csv(self, port_reset_dict): + def write_overall_csv(self, per_iteration_results): """ Aggregate client connection stats from all iterations and save a summary CSV (overall_reset.csv). """ - i_df = {} + totals_per_device = {} - for _, devices in port_reset_dict.items(): - if devices is None: + for _, iteration_metrics in per_iteration_results.items(): + if iteration_metrics is None: continue - for client, stats in devices.items(): - if client not in i_df: - i_df[client] = { + for device_eid, metrics in iteration_metrics.items(): + if device_eid not in totals_per_device: + totals_per_device[device_eid] = { 'ConnectAttempt': 0, 'Disconnected': 0, 'Scanning': 0, @@ -1683,22 +1683,22 @@ def create_dict_csv(self, port_reset_dict): } # Use safe addition (handles None and missing keys) - i_df[client]['ConnectAttempt'] += stats.get('ConnectAttempt', 0) or 0 - i_df[client]['Disconnected'] += stats.get('Disconnected', 0) or 0 - i_df[client]['Scanning'] += stats.get('Scanning', 0) or 0 - i_df[client]['Association Rejection'] += stats.get('Association Rejection', 0) or 0 - i_df[client]['Connected'] += stats.get('Connected', 0) or 0 - i_df[client]['Iterations'] += 1 + totals_per_device[device_eid]['ConnectAttempt'] += metrics.get('ConnectAttempt', 0) or 0 + totals_per_device[device_eid]['Disconnected'] += metrics.get('Disconnected', 0) or 0 + totals_per_device[device_eid]['Scanning'] += metrics.get('Scanning', 0) or 0 + totals_per_device[device_eid]['Association Rejection'] += metrics.get('Association Rejection', 0) or 0 + totals_per_device[device_eid]['Connected'] += metrics.get('Connected', 0) or 0 + totals_per_device[device_eid]['Iterations'] += 1 # Create DataFrame - df_summary = pd.DataFrame.from_dict(i_df, orient='index').reset_index() - df_summary = df_summary.rename(columns={'index': 'Client'}) - self.result_df = df_summary.copy() + summary_df = pd.DataFrame.from_dict(totals_per_device, orient='index').reset_index() + summary_df = summary_df.rename(columns={'index': 'Client'}) + self.result_df = summary_df.copy() # Save and print - df_summary.to_csv(f"{self.report_path}/overall_reset.csv", index=False) + summary_df.to_csv(f"{self.report_path}/overall_reset.csv", index=False) if self.dowebgui: - df_summary.to_csv(f"{self.result_dir}/overall_reset.csv", index=False) - print(df_summary) + summary_df.to_csv(f"{self.result_dir}/overall_reset.csv", index=False) + print(summary_df) def main(): From c0f6d7bc5c291ae7904c0b7a7cf79146fc86c32a Mon Sep 17 00:00:00 2001 From: Narayana-CT Date: Fri, 21 Aug 2026 15:44:25 +0530 Subject: [PATCH 06/13] lf_interop_port_reset_test.py: clarify naming in generate_overall_graph(), per_client_graph() and generate_overall_graph_table() Signed-off-by: Narayana-CT --- py-scripts/lf_interop_port_reset_test.py | 310 +++++++++++------------ 1 file changed, 155 insertions(+), 155 deletions(-) diff --git a/py-scripts/lf_interop_port_reset_test.py b/py-scripts/lf_interop_port_reset_test.py index 869df6bcb..145018ed4 100755 --- a/py-scripts/lf_interop_port_reset_test.py +++ b/py-scripts/lf_interop_port_reset_test.py @@ -997,108 +997,108 @@ def run(self): except Exception as e: logger.error(str(e)) - def generate_overall_graph(self, reset_dict=None, figsize=(13, 5), _alignmen=None, remove_border=None, + def generate_overall_graph(self, per_iteration_results=None, figsize=(13, 5), _alignment=None, remove_border=None, bar_width=0.7, _legend_handles=None, _legend_loc="best", _legend_box=None, _legend_ncol=1, _legend_fontsize=None, text_font=12, bar_text_rotation=45, graph_suffix=""): - dict_ = ['Port Resets', 'Disconnected', 'Scans', 'Assoc Attempts', "Association Rejection", 'Connected'] - data = dict.fromkeys(dict_) - data['Port Resets'] = self.iterations * len(self.all_selected_devices) - - conected_list, laptop_conected_list = [], [] - disconnected_list, laptop_disconnected_list = [], [] - scan_state, laptop_scan_state = [], [] - asso_attempt, laptop_asso_attempt = [], [] - asso_rej, laptop_asso_rej = [], [] - - for j in self.adb_device_list: - local = [] - local_2, local_3, local_4, local_5, local_6 = [], [], [], [], [] - for i in reset_dict: - if j in list(reset_dict[i].keys()): - local.append(reset_dict[i][j]['Connected']) - local_2.append(reset_dict[i][j]['Disconnected']) - local_3.append(reset_dict[i][j]['Scanning']) - local_4.append(reset_dict[i][j]['ConnectAttempt']) - local_5.append(reset_dict[i][j]["Association Rejection"]) - - conected_list.append(local) - disconnected_list.append(local_2) - scan_state.append(local_3) - asso_attempt.append(local_4) - asso_rej.append(local_5) - - for j in self.all_laptops: - local = [] - local_2, local_3, local_4, local_5, local_6 = [], [], [], [], [] # noqa: F841 - for i in reset_dict: - if j in list(reset_dict[i].keys()): - local.append(reset_dict[i][j]['Connected']) - local_2.append(reset_dict[i][j]['Disconnected']) - local_3.append(reset_dict[i][j]['Scanning']) - local_4.append(reset_dict[i][j]['ConnectAttempt']) - local_5.append(reset_dict[i][j]["Association Rejection"]) - - conected_list.append(local) - disconnected_list.append(local_2) - scan_state.append(local_3) - asso_attempt.append(local_4) - asso_rej.append(local_5) - conected_list = conected_list + laptop_conected_list - disconnected_list = disconnected_list + laptop_disconnected_list - scan_state = scan_state + laptop_scan_state - asso_attempt = asso_attempt + laptop_asso_attempt - asso_rej = asso_rej + laptop_asso_rej + metric_labels = ['Port Resets', 'Disconnected', 'Scans', 'Assoc Attempts', "Association Rejection", 'Connected'] + metric_totals = dict.fromkeys(metric_labels) + metric_totals['Port Resets'] = self.iterations * len(self.all_selected_devices) + + connected_counts, laptop_connected_counts = [], [] + disconnected_counts, laptop_disconnected_counts = [], [] + scan_counts, laptop_scan_counts = [], [] + assoc_attempt_counts, laptop_assoc_attempt_counts = [], [] + assoc_rejection_counts, laptop_assoc_rejection_counts = [], [] + + for device_eid in self.adb_device_list: + connected = [] + disconnected, scanning, assoc_attempts, assoc_rejections = [], [], [], [] + for iteration in per_iteration_results: + if device_eid in list(per_iteration_results[iteration].keys()): + connected.append(per_iteration_results[iteration][device_eid]['Connected']) + disconnected.append(per_iteration_results[iteration][device_eid]['Disconnected']) + scanning.append(per_iteration_results[iteration][device_eid]['Scanning']) + assoc_attempts.append(per_iteration_results[iteration][device_eid]['ConnectAttempt']) + assoc_rejections.append(per_iteration_results[iteration][device_eid]["Association Rejection"]) + + connected_counts.append(connected) + disconnected_counts.append(disconnected) + scan_counts.append(scanning) + assoc_attempt_counts.append(assoc_attempts) + assoc_rejection_counts.append(assoc_rejections) + + for device_eid in self.all_laptops: + connected = [] + disconnected, scanning, assoc_attempts, assoc_rejections = [], [], [], [] + for iteration in per_iteration_results: + if device_eid in list(per_iteration_results[iteration].keys()): + connected.append(per_iteration_results[iteration][device_eid]['Connected']) + disconnected.append(per_iteration_results[iteration][device_eid]['Disconnected']) + scanning.append(per_iteration_results[iteration][device_eid]['Scanning']) + assoc_attempts.append(per_iteration_results[iteration][device_eid]['ConnectAttempt']) + assoc_rejections.append(per_iteration_results[iteration][device_eid]["Association Rejection"]) + + connected_counts.append(connected) + disconnected_counts.append(disconnected) + scan_counts.append(scanning) + assoc_attempt_counts.append(assoc_attempts) + assoc_rejection_counts.append(assoc_rejections) + connected_counts = connected_counts + laptop_connected_counts + disconnected_counts = disconnected_counts + laptop_disconnected_counts + scan_counts = scan_counts + laptop_scan_counts + assoc_attempt_counts = assoc_attempt_counts + laptop_assoc_attempt_counts + assoc_rejection_counts = assoc_rejection_counts + laptop_assoc_rejection_counts # count connects and disconnects - scan, ass_atmpt = 0, 0 - for i, _ in zip(range(len(scan_state)), range(len(asso_attempt))): - for m in scan_state[i]: - scan = scan + m - for n in asso_attempt[i]: - ass_atmpt = ass_atmpt + int(n) - - conects, disconnects = 0, 0 - for i, _ in zip(range(len(conected_list)), range(len(disconnected_list))): - for m in conected_list[i]: - conects = conects + m - for n in disconnected_list[i]: - disconnects = disconnects + n - - assorej = 0 - for i in (range(len(asso_rej))): - for m in asso_rej[i]: - assorej = assorej + m - - data['Disconnected'] = disconnects - data['Scans'] = scan - data['Assoc Attempts'] = ass_atmpt - data['Connected'] = conects - data["Association Rejection"] = assorej - # print("Final data for overall graph: ", data) + scan_total, assoc_attempt_total = 0, 0 + for index, _ in zip(range(len(scan_counts)), range(len(assoc_attempt_counts))): + for count in scan_counts[index]: + scan_total = scan_total + count + for count in assoc_attempt_counts[index]: + assoc_attempt_total = assoc_attempt_total + int(count) + + connect_total, disconnect_total = 0, 0 + for index, _ in zip(range(len(connected_counts)), range(len(disconnected_counts))): + for count in connected_counts[index]: + connect_total = connect_total + count + for count in disconnected_counts[index]: + disconnect_total = disconnect_total + count + + assoc_rejection_total = 0 + for index in (range(len(assoc_rejection_counts))): + for count in assoc_rejection_counts[index]: + assoc_rejection_total = assoc_rejection_total + count + + metric_totals['Disconnected'] = disconnect_total + metric_totals['Scans'] = scan_total + metric_totals['Assoc Attempts'] = assoc_attempt_total + metric_totals['Connected'] = connect_total + metric_totals["Association Rejection"] = assoc_rejection_total + # print("Final data for overall graph: ", metric_totals) # creating the dataset self.graph_image_name = f"overall_graph{graph_suffix}" - courses = list(data.keys()) - values = list(data.values()) + bar_labels = list(metric_totals.keys()) + bar_totals = list(metric_totals.values()) - fig_size, ax = plt.subplots(figsize=figsize, gridspec_kw=_alignmen) + fig, ax = plt.subplots(figsize=figsize, gridspec_kw=_alignment) # to remove the borders if remove_border is not None: for border in remove_border: ax.spines[border].set_color(None) if 'left' in remove_border: # to remove the y-axis labeling - yaxis_visable = False + yaxis_visible = False else: - yaxis_visable = True - ax.yaxis.set_visible(yaxis_visable) + yaxis_visible = True + ax.yaxis.set_visible(yaxis_visible) # creating the bar plot colors = ('#f56122', '#00FF00', '#f5ea22', '#3D85C6', '#fa4d4d', "forestgreen") - for bar_values, color, i in zip(values, colors, range(len(courses))): - plt.bar(courses[i], bar_values, color=color, width=bar_width) - for item, value in enumerate(values): - plt.text(item, value, "{value}".format(value=value), ha='center', rotation=bar_text_rotation, + for bar_total, color, index in zip(bar_totals, colors, range(len(bar_labels))): + plt.bar(bar_labels[index], bar_total, color=color, width=bar_width) + for index, value in enumerate(bar_totals): + plt.text(index, value, "{value}".format(value=value), ha='center', rotation=bar_text_rotation, fontsize=text_font) plt.xlabel("", fontweight='bold', fontsize=15) @@ -1115,32 +1115,32 @@ def generate_overall_graph(self, reset_dict=None, figsize=(13, 5), _alignmen=Non plt.savefig("%s.png" % self.graph_image_name, dpi=96) return "%s.png" % self.graph_image_name - def per_client_graph(self, data=None, name=None, figsize=(13, 5), _alignmen=None, remove_border=None, bar_width=0.5, + def per_client_graph(self, metric_totals=None, image_name=None, figsize=(13, 5), _alignment=None, remove_border=None, bar_width=0.5, _legend_loc="best", _legend_box=None, _legend_fontsize=None, text_font=12, bar_text_rotation=45, xaxis_name="", yaxis_name="", graph_title_size=16, graph_title="Client %s Performance Port Reset Totals"): - self.graph_image_name = name - courses = list(data.keys()) - values = list(data.values()) + self.graph_image_name = image_name + bar_labels = list(metric_totals.keys()) + bar_totals = list(metric_totals.values()) # fig = plt.figure(figsize=(12, 4)) - fig_size, ax = plt.subplots(figsize=figsize, gridspec_kw=_alignmen) + fig, ax = plt.subplots(figsize=figsize, gridspec_kw=_alignment) # to remove the borders if remove_border is not None: for border in remove_border: ax.spines[border].set_color(None) if 'left' in remove_border: # to remove the y-axis labeling - yaxis_visable = False + yaxis_visible = False else: - yaxis_visable = True - ax.yaxis.set_visible(yaxis_visable) + yaxis_visible = True + ax.yaxis.set_visible(yaxis_visible) # creating the bar plot colors = ('#f56122', '#00FF00', '#f5ea22', '#3D85C6', '#fa4d4d', "forestgreen") - for bar_values, color, i in zip(values, colors, range(len(courses))): - plt.bar(courses[i], bar_values, color=color, width=bar_width) - for item, value in enumerate(values): - plt.text(item, value, "{value}".format(value=value), ha='center', va='bottom', rotation=bar_text_rotation, + for bar_total, color, index in zip(bar_totals, colors, range(len(bar_labels))): + plt.bar(bar_labels[index], bar_total, color=color, width=bar_width) + for index, value in enumerate(bar_totals): + plt.text(index, value, "{value}".format(value=value), ha='center', va='bottom', rotation=bar_text_rotation, fontsize=text_font) plt.xlabel(xaxis_name, fontweight='bold', fontsize=15) @@ -1154,69 +1154,69 @@ def per_client_graph(self, data=None, name=None, figsize=(13, 5), _alignmen=None plt.suptitle(graph_title, fontsize=graph_title_size) plt.savefig("%s.png" % self.graph_image_name, dpi=96) # generate csv - print(data) - df = pd.DataFrame(data=data, index=[1]) + print(metric_totals) + df = pd.DataFrame(data=metric_totals, index=[1]) print(df) - df.to_csv('{}/{}.csv'.format(self.report_path, name)) + df.to_csv('{}/{}.csv'.format(self.report_path, image_name)) return "%s.png" % self.graph_image_name - def generate_overall_graph_table(self, reset_dict, device_list): + def generate_overall_graph_table(self, per_iteration_results, device_list): if self.robot_test: self.total_resets, self.total_disconnects, self.total_scans, self.total_assoc_attempts, self.total_assoc_rejections, self.total_connects = [], [], [], [], [], [] - for y, _ in zip(device_list, range(len(device_list))): - reset_count_ = list(reset_dict.keys()) - reset_count = [] - for i in reset_count_: - reset_count.append(int(i) + 1) - asso_attempts, disconnected, scanning, connected, assorej, remarks = [], [], [], [], [], [] - - for i in reset_dict: - asso_attempts.append(reset_dict[i][y]["ConnectAttempt"]) - disconnected.append(reset_dict[i][y]["Disconnected"]) - scanning.append(reset_dict[i][y]["Scanning"]) - connected.append(reset_dict[i][y]["Connected"]) - assorej.append(reset_dict[i][y]["Association Rejection"]) - remarks.append(reset_dict[i][y]["Remarks"]) + for device_eid, _ in zip(device_list, range(len(device_list))): + iteration_indexes = list(per_iteration_results.keys()) + iteration_numbers = [] + for iteration_index in iteration_indexes: + iteration_numbers.append(int(iteration_index) + 1) + assoc_attempts, disconnected, scanning, connected, assoc_rejections, remarks = [], [], [], [], [], [] + + for iteration in per_iteration_results: + assoc_attempts.append(per_iteration_results[iteration][device_eid]["ConnectAttempt"]) + disconnected.append(per_iteration_results[iteration][device_eid]["Disconnected"]) + scanning.append(per_iteration_results[iteration][device_eid]["Scanning"]) + connected.append(per_iteration_results[iteration][device_eid]["Connected"]) + assoc_rejections.append(per_iteration_results[iteration][device_eid]["Association Rejection"]) + remarks.append(per_iteration_results[iteration][device_eid]["Remarks"]) # graph calculation - dict_ = ['Port Resets', 'Disconnects', 'Scans', 'Association Attempts', "Association Rejections", - 'Connects'] - data = dict.fromkeys(dict_) - data['Port Resets'] = self.iterations - - dis = 0 - for i in disconnected: - dis = dis + i - data['Disconnects'] = dis - - scan = 0 - for i in scanning: - scan = scan + i - data['Scans'] = scan - - asso = 0 - for i in asso_attempts: - asso = asso + i - data['Association Attempts'] = asso - - asso_rej = 0 - for i in assorej: - asso_rej = asso_rej + i - data["Association Rejections"] = asso_rej - - con = 0 - for i in connected: - con = con + i - data['Connects'] = con - - # print(f"Final data for per client graph for {y}: {data}") + metric_labels = ['Port Resets', 'Disconnects', 'Scans', 'Association Attempts', "Association Rejections", + 'Connects'] + metric_totals = dict.fromkeys(metric_labels) + metric_totals['Port Resets'] = self.iterations + + disconnect_total = 0 + for count in disconnected: + disconnect_total = disconnect_total + count + metric_totals['Disconnects'] = disconnect_total + + scan_total = 0 + for count in scanning: + scan_total = scan_total + count + metric_totals['Scans'] = scan_total + + assoc_attempt_total = 0 + for count in assoc_attempts: + assoc_attempt_total = assoc_attempt_total + count + metric_totals['Association Attempts'] = assoc_attempt_total + + assoc_rejection_total = 0 + for count in assoc_rejections: + assoc_rejection_total = assoc_rejection_total + count + metric_totals["Association Rejections"] = assoc_rejection_total + + connect_total = 0 + for count in connected: + connect_total = connect_total + count + metric_totals['Connects'] = connect_total + + # print(f"Final data for per client graph for {device_eid}: {metric_totals}") # fetching the total dissconnects, connects, ass_attemsts, ass_rejections, scans self.total_resets.append(self.iterations) self.total_disconnects.append(sum(disconnected)) self.total_scans.append(sum(scanning)) - self.total_assoc_attempts.append(sum(asso_attempts)) - self.total_assoc_rejections.append(sum(assorej)) + self.total_assoc_attempts.append(sum(assoc_attempts)) + self.total_assoc_rejections.append(sum(assoc_rejections)) self.total_connects.append(sum(connected)) def individual_client_info(self, reset_dict, device_list): @@ -1286,8 +1286,8 @@ def individual_client_info(self, reset_dict, device_list): self.lf_report.build_objective() # per client graph generation - graph2 = self.per_client_graph(data=data, name="per_client_" + str(z), figsize=(13, 5), - _alignmen={"left": 0.1}, remove_border=['top', 'right'], + graph2 = self.per_client_graph(metric_totals=data, image_name="per_client_" + str(z), figsize=(13, 5), + _alignment={"left": 0.1}, remove_border=['top', 'right'], _legend_loc="upper left", _legend_fontsize=9, _legend_box=(1, 1), yaxis_name="COUNT", graph_title="Client " + str(y) + " Total Reset Performance Graph") @@ -1371,7 +1371,7 @@ def generate_report(self, reset_dict=None, test_dur=None): # " Here real clients used is "+ str(self.clients) + "and number of resets provided is " + str(self.iterations) ) self.lf_report.build_objective() - graph1 = self.generate_overall_graph(reset_dict=reset_dict, figsize=(13, 5), _alignmen=None, bar_width=0.5, + graph1 = self.generate_overall_graph(per_iteration_results=reset_dict, figsize=(13, 5), _alignment=None, bar_width=0.5, _legend_loc="upper center", _legend_ncol=6, _legend_fontsize=10, _legend_box=(0.5, -0.06), text_font=12) # graph1 = self.generate_per_station_graph() @@ -1381,7 +1381,7 @@ def generate_report(self, reset_dict=None, test_dur=None): all_devices = self.adb_device_list + self.all_laptops - self.generate_overall_graph_table(reset_dict=reset_dict, device_list=all_devices) + self.generate_overall_graph_table(per_iteration_results=reset_dict, device_list=all_devices) d_name, device_type, model, user_name, release = [], [], [], [], [] # noqa: F841 for dev in self.adb_device_list: @@ -1539,7 +1539,7 @@ def generate_report_for_robo(self): self.lf_report.build_objective() graph_suffix = f"{self.coordinate_list[coordinate]}_{self.rotation_list[angle]}" - graph1 = self.generate_overall_graph(reset_dict=reset_dict, figsize=(13, 5), _alignmen=None, bar_width=0.5, + graph1 = self.generate_overall_graph(per_iteration_results=reset_dict, figsize=(13, 5), _alignment=None, bar_width=0.5, _legend_loc="upper center", _legend_ncol=6, _legend_fontsize=10, _legend_box=(0.5, -0.06), text_font=12, graph_suffix=graph_suffix) # graph1 = self.generate_per_station_graph() @@ -1548,7 +1548,7 @@ def generate_report_for_robo(self): self.lf_report.build_graph() all_devices = self.adb_device_list + self.all_laptops - self.generate_overall_graph_table(reset_dict=reset_dict, device_list=all_devices) + self.generate_overall_graph_table(per_iteration_results=reset_dict, device_list=all_devices) d_name, device_type, model, user_name, release = [], [], [], [], [] # noqa: F841 @@ -1603,7 +1603,7 @@ def generate_report_for_robo(self): _obj="") self.lf_report.build_objective() graph_suffix = f"{self.coordinate_list[coordinate]}" - graph1 = self.generate_overall_graph(reset_dict=reset_dict, figsize=(13, 5), _alignmen=None, bar_width=0.5, + graph1 = self.generate_overall_graph(per_iteration_results=reset_dict, figsize=(13, 5), _alignment=None, bar_width=0.5, _legend_loc="upper center", _legend_ncol=6, _legend_fontsize=10, _legend_box=(0.5, -0.06), text_font=12, graph_suffix=graph_suffix) # graph1 = self.generate_per_station_graph() @@ -1612,7 +1612,7 @@ def generate_report_for_robo(self): self.lf_report.build_graph() all_devices = self.adb_device_list + self.all_laptops - self.generate_overall_graph_table(reset_dict=reset_dict, device_list=all_devices) + self.generate_overall_graph_table(per_iteration_results=reset_dict, device_list=all_devices) d_name, device_type, model, user_name, release = [], [], [], [], [] # noqa: F841 From ba22417a0e4b1988ae65661832361e43fdf7d2e7 Mon Sep 17 00:00:00 2001 From: Narayana-CT Date: Fri, 21 Aug 2026 15:59:02 +0530 Subject: [PATCH 07/13] lf_interop_port_reset_test.py: clarify naming in individual_client_info(), generate_report(), add_live_view_images_to_report(), generate_report_for_robo() and get_last_wifi_msg_timestamp() Signed-off-by: Narayana-CT --- py-scripts/lf_interop_port_reset_test.py | 393 ++++++++++++----------- 1 file changed, 197 insertions(+), 196 deletions(-) diff --git a/py-scripts/lf_interop_port_reset_test.py b/py-scripts/lf_interop_port_reset_test.py index 145018ed4..28a46de56 100755 --- a/py-scripts/lf_interop_port_reset_test.py +++ b/py-scripts/lf_interop_port_reset_test.py @@ -275,17 +275,17 @@ def remove_files_with_duplicate_names(self, folder_path): # Adding the file name to the dictionary file_names[file_name] = file_path - def get_last_wifi_msg(self): - a = self.json_get_with_retry("/wifi-msgs/last/1", debug_=True) + def get_last_wifi_msg_timestamp(self): + response = self.json_get_with_retry("/wifi-msgs/last/1", debug_=True) try: - last = a['wifi-messages']['time-stamp'] + last_timestamp = response['wifi-messages']['time-stamp'] except (TypeError, KeyError) as e: logging.error( - f"get_last_wifi_msg: LANforge response is not in expected format ({e}). Data received: {a}") + f"get_last_wifi_msg_timestamp: LANforge response is not in expected format ({e}). Data received: {response}") logging.warning("Could not establish a wifi-msgs baseline timestamp; falling back to 'NA' for this reset.") return "NA" - logging.info(f"Last WiFi Message Time Stamp: {last}") - return last + logging.info(f"Last WiFi Message Time Stamp: {last_timestamp}") + return last_timestamp def count_wifi_msg_matches(self, wifi_messages=None, message_keys=None, device_eid=None, match_text=None): matches = [] @@ -766,7 +766,7 @@ def performing_resets(self, test_start_time=None): logging.info(f"Final dict: {device_metrics}") # note last log time - since_time = self.get_last_wifi_msg() + since_time = self.get_last_wifi_msg_timestamp() for device_eid in self.adb_device_list: self.interop.stop(device=device_eid) @@ -973,7 +973,7 @@ def run(self): self.current_coordinate = self.coordinate_list[coordinate_index] if not self.rotation_enabled: per_iteration_results, test_duration = self.performing_resets(test_start_time=test_start_time) - self.port_reset_data[self.coordinate_list[coordinate_index]] = {'reset_dict': per_iteration_results, 'test_duration': test_duration} + self.port_reset_data[self.coordinate_list[coordinate_index]] = {'per_iteration_results': per_iteration_results, 'test_duration': test_duration} time.sleep(10) else: for angle_index in range(len(self.rotation_list)): @@ -988,7 +988,8 @@ def run(self): per_iteration_results, test_duration = self.performing_resets(test_start_time=test_start_time) if self.coordinate_list[coordinate_index] not in self.port_reset_data: self.port_reset_data[self.coordinate_list[coordinate_index]] = {} - self.port_reset_data[self.coordinate_list[coordinate_index]][self.rotation_list[angle_index]] = {'reset_dict': per_iteration_results, 'test_duration': test_duration} + self.port_reset_data[self.coordinate_list[coordinate_index]][self.rotation_list[angle_index]] = { + 'per_iteration_results': per_iteration_results, 'test_duration': test_duration} time.sleep(10) if test_stopped_by_user or self.robo_test_stopped: @@ -1219,104 +1220,104 @@ def generate_overall_graph_table(self, per_iteration_results, device_list): self.total_assoc_rejections.append(sum(assoc_rejections)) self.total_connects.append(sum(connected)) - def individual_client_info(self, reset_dict, device_list): + def individual_client_info(self, per_iteration_results, device_list): # per client table and graphs # self.total_resets, self.total_disconnects, self.total_scans, self.total_assoc_attempts, self.total_assoc_rejections, self.total_connects = [], [], [], [], [], [] - for y, z in zip(device_list, range(len(device_list))): - reset_count_ = list(reset_dict.keys()) - reset_count = [] - for i in reset_count_: - reset_count.append(int(i) + 1) - asso_attempts, disconnected, scanning, connected, assorej, remarks, cx_times = [], [], [], [], [], [], [] - - for i in reset_dict: - asso_attempts.append(reset_dict[i][y]["ConnectAttempt"]) - disconnected.append(reset_dict[i][y]["Disconnected"]) - scanning.append(reset_dict[i][y]["Scanning"]) - connected.append(reset_dict[i][y]["Connected"]) - assorej.append(reset_dict[i][y]["Association Rejection"]) - remarks.append(reset_dict[i][y]["Remarks"]) - cx_times.append(reset_dict[i][y]["cx time (us)"]) + for device_eid, device_index in zip(device_list, range(len(device_list))): + iteration_indexes = list(per_iteration_results.keys()) + iteration_numbers = [] + for iteration in iteration_indexes: + iteration_numbers.append(int(iteration) + 1) + assoc_attempts, disconnected, scanning, connected, assoc_rejections, remarks, cx_times = [], [], [], [], [], [], [] + + for iteration in per_iteration_results: + assoc_attempts.append(per_iteration_results[iteration][device_eid]["ConnectAttempt"]) + disconnected.append(per_iteration_results[iteration][device_eid]["Disconnected"]) + scanning.append(per_iteration_results[iteration][device_eid]["Scanning"]) + connected.append(per_iteration_results[iteration][device_eid]["Connected"]) + assoc_rejections.append(per_iteration_results[iteration][device_eid]["Association Rejection"]) + remarks.append(per_iteration_results[iteration][device_eid]["Remarks"]) + cx_times.append(per_iteration_results[iteration][device_eid]["cx time (us)"]) # graph calculation - dict_ = ['Port Resets', 'Disconnects', 'Scans', 'Association Attempts', "Association Rejections", - 'Connects'] - data = dict.fromkeys(dict_) - data['Port Resets'] = self.iterations - - dis = 0 - for i in disconnected: - dis = dis + i - data['Disconnects'] = dis - - scan = 0 - for i in scanning: - scan = scan + i - data['Scans'] = scan - - asso = 0 - for i in asso_attempts: - asso = asso + i - data['Association Attempts'] = asso - - asso_rej = 0 - for i in assorej: - asso_rej = asso_rej + i - data["Association Rejections"] = asso_rej - - con = 0 - for i in connected: - con = con + i - data['Connects'] = con - - # print(f"Final data for per client graph for {y}: {data}") - - if "1.1." in y: + metric_labels = ['Port Resets', 'Disconnects', 'Scans', 'Association Attempts', "Association Rejections", + 'Connects'] + metric_totals = dict.fromkeys(metric_labels) + metric_totals['Port Resets'] = self.iterations + + disconnect_total = 0 + for count in disconnected: + disconnect_total = disconnect_total + count + metric_totals['Disconnects'] = disconnect_total + + scan_total = 0 + for count in scanning: + scan_total = scan_total + count + metric_totals['Scans'] = scan_total + + assoc_attempt_total = 0 + for count in assoc_attempts: + assoc_attempt_total = assoc_attempt_total + count + metric_totals['Association Attempts'] = assoc_attempt_total + + assoc_rejection_total = 0 + for count in assoc_rejections: + assoc_rejection_total = assoc_rejection_total + count + metric_totals["Association Rejections"] = assoc_rejection_total + + connect_total = 0 + for count in connected: + connect_total = connect_total + count + metric_totals['Connects'] = connect_total + + # print(f"Final data for per client graph for {device_eid}: {metric_totals}") + + if "1.1." in device_eid: # setting the title for per client graph and table represent title. - adb_user_name = self.interop.get_device_details(device=y, query="user-name") + android_user_name = self.interop.get_device_details(device=device_eid, query="user-name") self.lf_report.set_obj_html( - "Port Resets for Client " + str(adb_user_name) + " (" + str(y.split(".")[2]) + ")", - "The below table & graph displays details of " + str(adb_user_name) + " device.") + "Port Resets for Client " + str(android_user_name) + " (" + str(device_eid.split(".")[2]) + ")", + "The below table & graph displays details of " + str(android_user_name) + " device.") self.lf_report.build_objective() else: # setting the title for per client graph and table represent title. self.lf_report.set_obj_html( - "Port Resets for Client " + str(y) + ".", - "The below table & graph displays details of " + str(y) + " device.") + "Port Resets for Client " + str(device_eid) + ".", + "The below table & graph displays details of " + str(device_eid) + " device.") self.lf_report.build_objective() # per client graph generation - graph2 = self.per_client_graph(metric_totals=data, image_name="per_client_" + str(z), figsize=(13, 5), - _alignment={"left": 0.1}, remove_border=['top', 'right'], - _legend_loc="upper left", _legend_fontsize=9, _legend_box=(1, 1), - yaxis_name="COUNT", - graph_title="Client " + str(y) + " Total Reset Performance Graph") + client_graph = self.per_client_graph(metric_totals=metric_totals, image_name="per_client_" + str(device_index), figsize=(13, 5), + _alignment={"left": 0.1}, remove_border=['top', 'right'], + _legend_loc="upper left", _legend_fontsize=9, _legend_box=(1, 1), + yaxis_name="COUNT", + graph_title="Client " + str(device_eid) + " Total Reset Performance Graph") # graph1 = self.generate_per_station_graph() - self.lf_report.set_graph_image(graph2) + self.lf_report.set_graph_image(client_graph) self.lf_report.move_graph_image() self.lf_report.build_graph() # per client table data - table_1 = { - "Reset Count": reset_count, + per_iteration_table = { + "Reset Count": iteration_numbers, "Disconnected": disconnected, "Scanning": scanning, - "Association attempts": asso_attempts, - "Association Rejection": assorej, + "Association attempts": assoc_attempts, + "Association Rejection": assoc_rejections, "Connected": connected, "Connection Time (us)": cx_times, "Remarks": remarks } - test_setup = pd.DataFrame(table_1) - self.lf_report.set_table_dataframe(test_setup) + client_table_df = pd.DataFrame(per_iteration_table) + self.lf_report.set_table_dataframe(client_table_df) self.lf_report.build_table() - self.lf_report.save_csv('overall_report.csv', test_setup) + self.lf_report.save_csv('overall_report.csv', client_table_df) - def generate_report(self, reset_dict=None, test_dur=None): + def generate_report(self, per_iteration_results=None, test_duration=None): try: - # print("reset dict", reset_dict) - # print("Test Duration", test_dur) - # logging.info("reset dict " + str(reset_dict)) + # print("per iteration results", per_iteration_results) + # print("Test Duration", test_duration) + # logging.info("per iteration results " + str(per_iteration_results)) date = str(datetime.now()).split(",")[0].replace(" ", "-").split(".")[0] security = "" @@ -1337,7 +1338,7 @@ def generate_report(self, reset_dict=None, test_dur=None): "No of Clients": f"{len(self.all_selected_devices)} (Windows: {len(self.windows_list)}, Linux: {len(self.linux_list)}, Mac: {len(self.mac_list)}, Android: {len(self.adb_device_list)})", # noqa: E501 # "Wait Time": str(self.wait_time) + " sec", "Time interval between resets": str(self.reset_interval_sec) + " sec", - "Test Duration": test_dur, + "Test Duration": test_duration, } self.lf_report.set_title("Port Reset Test") self.lf_report.set_date(date) @@ -1371,45 +1372,45 @@ def generate_report(self, reset_dict=None, test_dur=None): # " Here real clients used is "+ str(self.clients) + "and number of resets provided is " + str(self.iterations) ) self.lf_report.build_objective() - graph1 = self.generate_overall_graph(per_iteration_results=reset_dict, figsize=(13, 5), _alignment=None, bar_width=0.5, - _legend_loc="upper center", _legend_ncol=6, _legend_fontsize=10, - _legend_box=(0.5, -0.06), text_font=12) + overall_graph = self.generate_overall_graph(per_iteration_results=per_iteration_results, figsize=(13, 5), _alignment=None, bar_width=0.5, + _legend_loc="upper center", _legend_ncol=6, _legend_fontsize=10, + _legend_box=(0.5, -0.06), text_font=12) # graph1 = self.generate_per_station_graph() - self.lf_report.set_graph_image(graph1) + self.lf_report.set_graph_image(overall_graph) self.lf_report.move_graph_image() self.lf_report.build_graph() all_devices = self.adb_device_list + self.all_laptops - self.generate_overall_graph_table(per_iteration_results=reset_dict, device_list=all_devices) - - d_name, device_type, model, user_name, release = [], [], [], [], [] # noqa: F841 - for dev in self.adb_device_list: - d_name.append(self.interop.get_device_details(device=dev, query="name")) - device_type.append(self.interop.get_device_details(device=dev, query="device-type")) - user_name.append(self.interop.get_device_details(device=dev, query="user-name")) - for dev in self.all_laptops: - d_name.append(dev) - user_name.append(self.interop.get_laptop_devices_details(device=dev, query="host_name")) - hw_version = self.interop.get_laptop_devices_details(device=dev, query="hw_version") + self.generate_overall_graph_table(per_iteration_results=per_iteration_results, device_list=all_devices) + + device_names, device_types, model, user_names, release = [], [], [], [], [] # noqa: F841 + for device_eid in self.adb_device_list: + device_names.append(self.interop.get_device_details(device=device_eid, query="name")) + device_types.append(self.interop.get_device_details(device=device_eid, query="device-type")) + user_names.append(self.interop.get_device_details(device=device_eid, query="user-name")) + for device_eid in self.all_laptops: + device_names.append(device_eid) + user_names.append(self.interop.get_laptop_devices_details(device=device_eid, query="host_name")) + hw_version = self.interop.get_laptop_devices_details(device=device_eid, query="hw_version") if "Linux" in hw_version: - dev_type = "Linux" + device_type = "Linux" elif "Win" in hw_version: - dev_type = "Windows" + device_type = "Windows" elif "Apple" in hw_version: - dev_type = "Apple" + device_type = "Apple" else: - dev_type = "" - device_type.append(dev_type) - s_no = [] - for i in range(len(d_name)): - s_no.append(i + 1) - - table_2 = { - "S.No": s_no, - "Name of the Devices": d_name, - "Hardware Version": user_name, - "Device Type": device_type, + device_type = "" + device_types.append(device_type) + serial_numbers = [] + for index in range(len(device_names)): + serial_numbers.append(index + 1) + + device_summary_table = { + "S.No": serial_numbers, + "Name of the Devices": device_names, + "Hardware Version": user_names, + "Device Type": device_types, # "Model": model, # "SDK Release": release, "Port Resets": self.total_resets, @@ -1419,10 +1420,10 @@ def generate_report(self, reset_dict=None, test_dur=None): "Assoc Rejects": self.total_assoc_rejections, "Connects": self.total_connects } - test_setup = pd.DataFrame(table_2) - self.lf_report.set_table_dataframe(test_setup) + device_summary_df = pd.DataFrame(device_summary_table) + self.lf_report.set_table_dataframe(device_summary_df) self.lf_report.build_table() - self.individual_client_info(reset_dict=reset_dict, device_list=all_devices) + self.individual_client_info(per_iteration_results=per_iteration_results, device_list=all_devices) # self.lf_report.set_obj_html("Tested Clients Information:", # "The table displays details of real clients which are involved in the test.") # self.lf_report.build_objective() @@ -1446,19 +1447,19 @@ def add_live_view_images_to_report(self): it's added to the `report` on a new page; otherwise, it's skipped. """ for floor in range(0, int(self.total_floors)): - port_reset_img_path = os.path.join(self.result_dir, "live_view_images", f"port_reset_{self.test_name}_{floor + 1}.png") - timeout = 60 # seconds + port_reset_image_path = os.path.join(self.result_dir, "live_view_images", f"port_reset_{self.test_name}_{floor + 1}.png") + timeout_sec = 60 start_time = time.time() - while not (os.path.exists(port_reset_img_path)): - if time.time() - start_time > timeout: + while not (os.path.exists(port_reset_image_path)): + if time.time() - start_time > timeout_sec: logging.info("Timeout: Images not found within 60 seconds.") break time.sleep(1) - if os.path.exists(port_reset_img_path): + if os.path.exists(port_reset_image_path): self.lf_report.set_custom_html('
') self.lf_report.build_custom() - self.lf_report.set_custom_html(f'') + self.lf_report.set_custom_html(f'') self.lf_report.build_custom() def generate_report_for_robo(self): @@ -1521,63 +1522,63 @@ def generate_report_for_robo(self): # " Here real clients used is "+ str(self.clients) + "and number of resets provided is " + str(self.iterations) ) self.lf_report.build_objective() - for coordinate in range(len(self.coordinate_list)): + for coordinate_index in range(len(self.coordinate_list)): if self.rotation_enabled: - for angle in range(len(self.rotation_list)): - coord_key = self.coordinate_list[coordinate] - angle_key = self.rotation_list[angle] + for angle_index in range(len(self.rotation_list)): + coordinate = self.coordinate_list[coordinate_index] + angle = self.rotation_list[angle_index] if ( - coord_key not in self.port_reset_data or - angle_key not in self.port_reset_data[coord_key] or - 'reset_dict' not in self.port_reset_data[coord_key][angle_key] + coordinate not in self.port_reset_data or + angle not in self.port_reset_data[coordinate] or + 'per_iteration_results' not in self.port_reset_data[coordinate][angle] ): continue - reset_dict = self.port_reset_data[coord_key][angle_key]['reset_dict'] - self.lf_report.set_obj_html(_obj_title=f"Overall Port reset stats at Coordinate: {self.coordinate_list[coordinate]} | Rotation Angle: {self.rotation_list[angle]}°", + per_iteration_results = self.port_reset_data[coordinate][angle]['per_iteration_results'] + self.lf_report.set_obj_html(_obj_title=f"Overall Port reset stats at Coordinate: {self.coordinate_list[coordinate_index]} | Rotation Angle: {self.rotation_list[angle_index]}°", _obj="") self.lf_report.build_objective() - graph_suffix = f"{self.coordinate_list[coordinate]}_{self.rotation_list[angle]}" - graph1 = self.generate_overall_graph(per_iteration_results=reset_dict, figsize=(13, 5), _alignment=None, bar_width=0.5, - _legend_loc="upper center", _legend_ncol=6, _legend_fontsize=10, - _legend_box=(0.5, -0.06), text_font=12, graph_suffix=graph_suffix) + graph_suffix = f"{self.coordinate_list[coordinate_index]}_{self.rotation_list[angle_index]}" + overall_graph = self.generate_overall_graph(per_iteration_results=per_iteration_results, figsize=(13, 5), _alignment=None, bar_width=0.5, + _legend_loc="upper center", _legend_ncol=6, _legend_fontsize=10, + _legend_box=(0.5, -0.06), text_font=12, graph_suffix=graph_suffix) # graph1 = self.generate_per_station_graph() - self.lf_report.set_graph_image(graph1) + self.lf_report.set_graph_image(overall_graph) self.lf_report.move_graph_image() self.lf_report.build_graph() all_devices = self.adb_device_list + self.all_laptops - self.generate_overall_graph_table(per_iteration_results=reset_dict, device_list=all_devices) + self.generate_overall_graph_table(per_iteration_results=per_iteration_results, device_list=all_devices) - d_name, device_type, model, user_name, release = [], [], [], [], [] # noqa: F841 + device_names, device_types, model, user_names, release = [], [], [], [], [] # noqa: F841 - for dev in self.adb_device_list: - d_name.append(self.interop.get_device_details(device=dev, query="name")) - device_type.append(self.interop.get_device_details(device=dev, query="device-type")) - user_name.append(self.interop.get_device_details(device=dev, query="user-name")) - for dev in self.all_laptops: - d_name.append(dev) - user_name.append(self.interop.get_laptop_devices_details(device=dev, query="host_name")) - hw_version = self.interop.get_laptop_devices_details(device=dev, query="hw_version") + for device_eid in self.adb_device_list: + device_names.append(self.interop.get_device_details(device=device_eid, query="name")) + device_types.append(self.interop.get_device_details(device=device_eid, query="device-type")) + user_names.append(self.interop.get_device_details(device=device_eid, query="user-name")) + for device_eid in self.all_laptops: + device_names.append(device_eid) + user_names.append(self.interop.get_laptop_devices_details(device=device_eid, query="host_name")) + hw_version = self.interop.get_laptop_devices_details(device=device_eid, query="hw_version") if "Linux" in hw_version: - dev_type = "Linux" + device_type = "Linux" elif "Win" in hw_version: - dev_type = "Windows" + device_type = "Windows" elif "Apple" in hw_version: - dev_type = "Apple" + device_type = "Apple" else: - dev_type = "" - device_type.append(dev_type) - s_no = [] - for i in range(len(d_name)): - s_no.append(i + 1) - - table_2 = { - "S.No": s_no, - "Name of the Devices": d_name, - "Hardware Version": user_name, - "Device Type": device_type, + device_type = "" + device_types.append(device_type) + serial_numbers = [] + for index in range(len(device_names)): + serial_numbers.append(index + 1) + + device_summary_table = { + "S.No": serial_numbers, + "Name of the Devices": device_names, + "Hardware Version": user_names, + "Device Type": device_types, # "Model": model, # "SDK Release": release, "Port Resets": self.total_resets, @@ -1587,61 +1588,61 @@ def generate_report_for_robo(self): "Assoc Rejects": self.total_assoc_rejections, "Connects": self.total_connects } - test_setup = pd.DataFrame(table_2) - self.lf_report.set_table_dataframe(test_setup) + device_summary_df = pd.DataFrame(device_summary_table) + self.lf_report.set_table_dataframe(device_summary_df) self.lf_report.build_table() else: - coord_key = self.coordinate_list[coordinate] + coordinate = self.coordinate_list[coordinate_index] if ( - coord_key not in self.port_reset_data or - 'reset_dict' not in self.port_reset_data[coord_key] + coordinate not in self.port_reset_data or + 'per_iteration_results' not in self.port_reset_data[coordinate] ): continue - reset_dict = self.port_reset_data[coord_key]['reset_dict'] - self.lf_report.set_obj_html(_obj_title=f"Overall Port reset stats at Coordinate: {self.coordinate_list[coordinate]}", + per_iteration_results = self.port_reset_data[coordinate]['per_iteration_results'] + self.lf_report.set_obj_html(_obj_title=f"Overall Port reset stats at Coordinate: {self.coordinate_list[coordinate_index]}", _obj="") self.lf_report.build_objective() - graph_suffix = f"{self.coordinate_list[coordinate]}" - graph1 = self.generate_overall_graph(per_iteration_results=reset_dict, figsize=(13, 5), _alignment=None, bar_width=0.5, - _legend_loc="upper center", _legend_ncol=6, _legend_fontsize=10, - _legend_box=(0.5, -0.06), text_font=12, graph_suffix=graph_suffix) + graph_suffix = f"{self.coordinate_list[coordinate_index]}" + overall_graph = self.generate_overall_graph(per_iteration_results=per_iteration_results, figsize=(13, 5), _alignment=None, bar_width=0.5, + _legend_loc="upper center", _legend_ncol=6, _legend_fontsize=10, + _legend_box=(0.5, -0.06), text_font=12, graph_suffix=graph_suffix) # graph1 = self.generate_per_station_graph() - self.lf_report.set_graph_image(graph1) + self.lf_report.set_graph_image(overall_graph) self.lf_report.move_graph_image() self.lf_report.build_graph() all_devices = self.adb_device_list + self.all_laptops - self.generate_overall_graph_table(per_iteration_results=reset_dict, device_list=all_devices) + self.generate_overall_graph_table(per_iteration_results=per_iteration_results, device_list=all_devices) - d_name, device_type, model, user_name, release = [], [], [], [], [] # noqa: F841 + device_names, device_types, model, user_names, release = [], [], [], [], [] # noqa: F841 - for dev in self.adb_device_list: - d_name.append(self.interop.get_device_details(device=dev, query="name")) - device_type.append(self.interop.get_device_details(device=dev, query="device-type")) - user_name.append(self.interop.get_device_details(device=dev, query="user-name")) - for dev in self.all_laptops: - d_name.append(dev) - user_name.append(self.interop.get_laptop_devices_details(device=dev, query="host_name")) - hw_version = self.interop.get_laptop_devices_details(device=dev, query="hw_version") + for device_eid in self.adb_device_list: + device_names.append(self.interop.get_device_details(device=device_eid, query="name")) + device_types.append(self.interop.get_device_details(device=device_eid, query="device-type")) + user_names.append(self.interop.get_device_details(device=device_eid, query="user-name")) + for device_eid in self.all_laptops: + device_names.append(device_eid) + user_names.append(self.interop.get_laptop_devices_details(device=device_eid, query="host_name")) + hw_version = self.interop.get_laptop_devices_details(device=device_eid, query="hw_version") if "Linux" in hw_version: - dev_type = "Linux" + device_type = "Linux" elif "Win" in hw_version: - dev_type = "Windows" + device_type = "Windows" elif "Apple" in hw_version: - dev_type = "Apple" + device_type = "Apple" else: - dev_type = "" - device_type.append(dev_type) - s_no = [] - for i in range(len(d_name)): - s_no.append(i + 1) - - table_2 = { - "S.No": s_no, - "Name of the Devices": d_name, - "Hardware Version": user_name, - "Device Type": device_type, + device_type = "" + device_types.append(device_type) + serial_numbers = [] + for index in range(len(device_names)): + serial_numbers.append(index + 1) + + device_summary_table = { + "S.No": serial_numbers, + "Name of the Devices": device_names, + "Hardware Version": user_names, + "Device Type": device_types, # "Model": model, # "SDK Release": release, "Port Resets": self.total_resets, @@ -1651,8 +1652,8 @@ def generate_report_for_robo(self): "Assoc Rejects": self.total_assoc_rejections, "Connects": self.total_connects } - test_setup = pd.DataFrame(table_2) - self.lf_report.set_table_dataframe(test_setup) + device_summary_df = pd.DataFrame(device_summary_table) + self.lf_report.set_table_dataframe(device_summary_df) self.lf_report.build_table() self.lf_report.build_footer() self.lf_report.write_html() @@ -1887,7 +1888,7 @@ def main(): if port_reset_test.robot_test: port_reset_test.generate_report_for_robo() else: - port_reset_test.generate_report(reset_dict=per_iteration_results, test_dur=test_duration) + port_reset_test.generate_report(per_iteration_results=per_iteration_results, test_duration=test_duration) if __name__ == '__main__': From 82b6d98883d96e2bd49853accd79d9ee286ea7c3 Mon Sep 17 00:00:00 2001 From: Narayana-CT Date: Fri, 21 Aug 2026 16:06:20 +0530 Subject: [PATCH 08/13] lf_interop_port_reset_test.py: format using black Signed-off-by: Narayana-CT --- py-scripts/lf_interop_port_reset_test.py | 1966 +++++++++++++++------- 1 file changed, 1403 insertions(+), 563 deletions(-) diff --git a/py-scripts/lf_interop_port_reset_test.py b/py-scripts/lf_interop_port_reset_test.py index 28a46de56..9bc298d97 100755 --- a/py-scripts/lf_interop_port_reset_test.py +++ b/py-scripts/lf_interop_port_reset_test.py @@ -47,6 +47,7 @@ INCLUDE_IN_README: False """ + import json import sys import os @@ -54,6 +55,7 @@ import argparse import time import datetime + # When you use from datetime import datetime, you are making the # datetime class directly accessible in your code without # having to prefix it with the module name @@ -69,7 +71,7 @@ exit() sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../"))) interop_modify = importlib.import_module("py-scripts.lf_interop_modify") -base = importlib.import_module('py-scripts.lf_base_interop_profile') +base = importlib.import_module("py-scripts.lf_base_interop_profile") lf_csv = importlib.import_module("py-scripts.lf_csv") realm = importlib.import_module("py-json.realm") Realm = realm.Realm @@ -80,31 +82,32 @@ class InteropPortReset(Realm): - def __init__(self, lanforge_ip, - lanforge_port=8080, - dut=None, - ssid=None, - passwd=None, - encryption=None, - iterations=None, - upstream_port=None, - reset_interval_sec=None, - device_list=None, - android_releases=None, - forget_network=True, - dowebgui=False, - result_dir=None, - test_name=None, - robot_test=False, - robot_ip=None, - robot_port=None, - coordinate=None, - rotation=None, - get_live_view=False, - total_floors=0, - ): - super().__init__(lfclient_host=lanforge_ip, - lfclient_port=8080) + def __init__( + self, + lanforge_ip, + lanforge_port=8080, + dut=None, + ssid=None, + passwd=None, + encryption=None, + iterations=None, + upstream_port=None, + reset_interval_sec=None, + device_list=None, + android_releases=None, + forget_network=True, + dowebgui=False, + result_dir=None, + test_name=None, + robot_test=False, + robot_ip=None, + robot_port=None, + coordinate=None, + rotation=None, + get_live_view=False, + total_floors=0, + ): + super().__init__(lfclient_host=lanforge_ip, lfclient_port=8080) self.total_connects = [] self.total_assoc_rejections = [] self.total_assoc_attempts = [] @@ -149,19 +152,30 @@ def __init__(self, lanforge_ip, self.coordinate = coordinate self.rotation = rotation self.rotation_enabled = False - self.coordinate_list = coordinate.split(',') - self.rotation_list = rotation.split(',') + self.coordinate_list = coordinate.split(",") + self.rotation_list = rotation.split(",") self.current_coordinate = None self.current_angle = None self.android_releases = android_releases self.android_user_names = [] - self.lf_report = lf_report_pdf.lf_report(_path="" if not self.dowebgui else self.result_dir, _results_dir_name="Interop_port_reset_test", - _output_html="port_reset_test.html", - _output_pdf="port_reset_test.pdf") + self.lf_report = lf_report_pdf.lf_report( + _path="" if not self.dowebgui else self.result_dir, + _results_dir_name="Interop_port_reset_test", + _output_html="port_reset_test.html", + _output_pdf="port_reset_test.pdf", + ) self.report_path = self.lf_report.get_report_path() - self.base_interop_profile = base.RealDevice(manager_ip=self.lanforge_ip, server_ip=self.upstream_port, ssid_5g=self.ssid, - encryption_5g=self.encryption, passwd_5g=self.passwd, disconnect_devices=self.forget_network, reboot=False, selected_bands=["5g"]) + self.base_interop_profile = base.RealDevice( + manager_ip=self.lanforge_ip, + server_ip=self.upstream_port, + ssid_5g=self.ssid, + encryption_5g=self.encryption, + passwd_5g=self.passwd, + disconnect_devices=self.forget_network, + reboot=False, + selected_bands=["5g"], + ) self.utility = base.UtilityInteropWifi(host_ip=self.lanforge_ip) # logging.basicConfig(filename='port_reset.log', filemode='w', format='%(asctime)s - %(message)s', @@ -175,7 +189,9 @@ def json_get_with_retry(self, url, wait_time=40, poll_interval=5, debug_=False): start_time = time.time() response = self.json_get(url, debug_=debug_) while response is None and (time.time() - start_time) < wait_time: - logging.warning(f"GET {url} returned no response from LANforge; retrying...") + logging.warning( + f"GET {url} returned no response from LANforge; retrying..." + ) time.sleep(poll_interval) response = self.json_get(url, debug_=debug_) @@ -192,16 +208,21 @@ def change_port_to_ip(self, upstream_port): # for --upstream_port. This is only called once, at test start, and we cannot # proceed without a resolved manager IP, so retry for a while and then # abort instead of silently continuing with an unresolved port name. - if upstream_port.count('.') != 3: + if upstream_port.count(".") != 3: shelf, resource, port_name, _ = self.name_to_eid(upstream_port) - response = self.json_get_with_retry(f'/port/{shelf}/{resource}/{port_name}?fields=ip') + response = self.json_get_with_retry( + f"/port/{shelf}/{resource}/{port_name}?fields=ip" + ) try: - upstream_port = response['interface']['ip'] + upstream_port = response["interface"]["ip"] except (TypeError, KeyError) as e: logging.error( f"change_port_to_ip: could not resolve upstream port '{upstream_port}' to an IP; LANforge " - f"response is not in expected format ({e}). Data received: {response}") - logging.critical("Aborting the test: a valid manager IP is required to proceed.") + f"response is not in expected format ({e}). Data received: {response}" + ) + logging.critical( + "Aborting the test: a valid manager IP is required to proceed." + ) exit(1) logging.info(f"Upstream port IP {upstream_port}") else: @@ -212,43 +233,64 @@ def change_port_to_ip(self, upstream_port): def selecting_devices_from_available(self): # If device list is not provided by user, then it shows the available devices to choose from if self.device_list is None: - configurable_devices = self.base_interop_profile.query_all_devices_to_configure_wifi() + configurable_devices = ( + self.base_interop_profile.query_all_devices_to_configure_wifi() + ) else: - configurable_devices = self.base_interop_profile.query_all_devices_to_configure_wifi(device_list=self.device_list.split(',')) - asyncio.run(self.base_interop_profile.configure_wifi( - configurable_devices[0] + configurable_devices[1] + configurable_devices[2])) + configurable_devices = ( + self.base_interop_profile.query_all_devices_to_configure_wifi( + device_list=self.device_list.split(",") + ) + ) + asyncio.run( + self.base_interop_profile.configure_wifi( + configurable_devices[0] + + configurable_devices[1] + + configurable_devices[2] + ) + ) self.real_station_list = self.base_interop_profile.station_list logger.info(self.real_station_list) device_details = self.base_interop_profile.devices_data if len(self.real_station_list) == 0: - logging.error('There are no real devices in this testbed. Aborting the test.') + logging.error( + "There are no real devices in this testbed. Aborting the test." + ) # Added for the purpose to stop webui test when there are no selected devices available in lanforge. - raise RuntimeError("There are no real devices in this testbed. Aborting the test.") + raise RuntimeError( + "There are no real devices in this testbed. Aborting the test." + ) logging.info(f"{self.real_station_list}") for station_name in self.real_station_list: if station_name not in device_details: - logger.error('Real Station not in devices data') - raise ValueError('Real station not in devices data') + logger.error("Real Station not in devices data") + raise ValueError("Real station not in devices data") android_list = self.base_interop_profile.android_list - self.interop = base.BaseInteropWifi(manager_ip=self.lanforge_ip, - port=self.lanforge_port, - ssid=self.ssid, - passwd=self.passwd, - encryption=self.encryption, - release=self.android_releases, - screen_size_prcnt=0.4, - _debug_on=False, - _exit_on_error=False) + self.interop = base.BaseInteropWifi( + manager_ip=self.lanforge_ip, + port=self.lanforge_port, + ssid=self.ssid, + passwd=self.passwd, + encryption=self.encryption, + release=self.android_releases, + screen_size_prcnt=0.4, + _debug_on=False, + _exit_on_error=False, + ) supported_resource_ids = self.interop.supported_devices_resource_id print("Supported dict", supported_resource_ids) self.final_selected_android_list = [] for device_name in supported_resource_ids.keys(): if device_name != "": if any(device_name in item for item in android_list): - self.final_selected_android_list.append(supported_resource_ids[device_name]) - logging.info(f"Final Android Serial Numbers List: {self.final_selected_android_list}") + self.final_selected_android_list.append( + supported_resource_ids[device_name] + ) + logging.info( + f"Final Android Serial Numbers List: {self.final_selected_android_list}" + ) def create_log_file(self, json_list, file_name="empty.json"): # Convert the list of JSON values to a JSON-formatted string @@ -258,7 +300,7 @@ def create_log_file(self, json_list, file_name="empty.json"): os.makedirs(new_folder) file_path = f"{self.report_path}/Wifi_Messages/{file_name}" # Write the JSON-formatted string to the .json file - with open(file_path, 'w') as file: + with open(file_path, "w") as file: file.write(json_string) def remove_files_with_duplicate_names(self, folder_path): @@ -278,27 +320,34 @@ def remove_files_with_duplicate_names(self, folder_path): def get_last_wifi_msg_timestamp(self): response = self.json_get_with_retry("/wifi-msgs/last/1", debug_=True) try: - last_timestamp = response['wifi-messages']['time-stamp'] + last_timestamp = response["wifi-messages"]["time-stamp"] except (TypeError, KeyError) as e: logging.error( - f"get_last_wifi_msg_timestamp: LANforge response is not in expected format ({e}). Data received: {response}") - logging.warning("Could not establish a wifi-msgs baseline timestamp; falling back to 'NA' for this reset.") + f"get_last_wifi_msg_timestamp: LANforge response is not in expected format ({e}). Data received: {response}" + ) + logging.warning( + "Could not establish a wifi-msgs baseline timestamp; falling back to 'NA' for this reset." + ) return "NA" logging.info(f"Last WiFi Message Time Stamp: {last_timestamp}") return last_timestamp - def count_wifi_msg_matches(self, wifi_messages=None, message_keys=None, device_eid=None, match_text=None): + def count_wifi_msg_matches( + self, wifi_messages=None, message_keys=None, device_eid=None, match_text=None + ): matches = [] eid_parts = device_eid.split(".") port_name = eid_parts[2] resource_id = eid_parts[0] + "." + eid_parts[1] for message_key, index in zip(message_keys, range(len(message_keys))): - wifi_msg_text = wifi_messages[index][message_key]['text'] - message_resource = wifi_messages[index][message_key]['resource'] + wifi_msg_text = wifi_messages[index][message_key]["text"] + message_resource = wifi_messages[index][message_key]["resource"] if type(wifi_msg_text) is str: - message_tokens = wifi_messages[index][message_key]['text'].split(" ") + message_tokens = wifi_messages[index][message_key]["text"].split(" ") if port_name is None: - logging.info(f"Device {port_name} is None device name not existed in wifi messages...") + logging.info( + f"Device {port_name} is None device name not existed in wifi messages..." + ) else: if message_resource == resource_id: if port_name in message_tokens: @@ -307,7 +356,9 @@ def count_wifi_msg_matches(self, wifi_messages=None, message_keys=None, device_e matches.append("YES") else: match_tokens = match_text.split(" ") - if all(token in message_tokens for token in match_tokens): + if all( + token in message_tokens for token in match_tokens + ): # logging.info(f"The filter {match_tokens} sequence is present in Wi-Fi msg.") matches.append("YES") else: @@ -317,7 +368,10 @@ def count_wifi_msg_matches(self, wifi_messages=None, message_keys=None, device_e matches.append("YES") else: match_tokens = match_text.split(" ") - if all(token in message_tokens for token in match_tokens): + if all( + token in message_tokens + for token in match_tokens + ): # logging.info(f"The filter {match_tokens} sequence is present in Wi-Fi msg.") matches.append("YES") else: # if wifi_msg_text is list @@ -332,7 +386,10 @@ def count_wifi_msg_matches(self, wifi_messages=None, message_keys=None, device_e matches.append("YES") else: match_tokens = match_text.split(" ") - if all(token in message_tokens for token in match_tokens): + if all( + token in message_tokens + for token in match_tokens + ): # logging.info(f"The filter {match_tokens} sequence is present in Wi-Fi msg.") matches.append("YES") else: @@ -342,38 +399,70 @@ def count_wifi_msg_matches(self, wifi_messages=None, message_keys=None, device_e matches.append("YES") else: match_tokens = match_text.split(" ") - if all(token in message_tokens for token in match_tokens): + if all( + token in message_tokens + for token in match_tokens + ): # logging.info(f"The filter {match_tokens} sequence is present in Wi-Fi msg.") matches.append("YES") match_count = matches.count("YES") return match_count - def collect_device_metrics(self, device_metrics=None, device_eid=None, since_time=None, file_name="dummy.json", iteration=None): + def collect_device_metrics( + self, + device_metrics=None, + device_eid=None, + since_time=None, + file_name="dummy.json", + iteration=None, + ): # print("Waiting for 20 sec to fetch the logs...") # time.sleep(20) - wifi_msgs_response = self.json_get_with_retry("/wifi-msgs/since=time/" + str(since_time), debug_=True) + wifi_msgs_response = self.json_get_with_retry( + "/wifi-msgs/since=time/" + str(since_time), debug_=True + ) try: - wifi_messages = wifi_msgs_response['wifi-messages'] + wifi_messages = wifi_msgs_response["wifi-messages"] except (TypeError, KeyError) as e: logging.error( f"collect_device_metrics: LANforge response is not in expected format ({e}) while fetching " - f"wifi-msgs for device {device_eid}. Data received: {wifi_msgs_response}") - logging.warning(f"Defaulting device {device_eid} stats to 0 for this reset and continuing.") - for metric_name in ("ConnectAttempt", "Disconnected", "Scanning", "Association Rejection", "Connected"): + f"wifi-msgs for device {device_eid}. Data received: {wifi_msgs_response}" + ) + logging.warning( + f"Defaulting device {device_eid} stats to 0 for this reset and continuing." + ) + for metric_name in ( + "ConnectAttempt", + "Disconnected", + "Scanning", + "Association Rejection", + "Connected", + ): device_metrics[str(device_eid)][metric_name] = 0 - device_metrics[str(device_eid)]["Remarks"] = "Data unavailable - LANforge API error, stats defaulted to 0" + device_metrics[str(device_eid)][ + "Remarks" + ] = "Data unavailable - LANforge API error, stats defaulted to 0" device_metrics[str(device_eid)]["cx time (us)"] = "NA" self.write_iteration_csvs(device_metrics, iteration) return device_metrics # print("Wifi msgs Response : ", wifi_messages) logging.info( - f"Counting the DISCONNECTIONS, SCANNING, ASSOC ATTEMPTS, ASSOC RECJECTIONS, CONNECTS for device {device_eid}") + f"Counting the DISCONNECTIONS, SCANNING, ASSOC ATTEMPTS, ASSOC RECJECTIONS, CONNECTS for device {device_eid}" + ) if type(wifi_messages) is not list: - logging.info(f"Device {device_eid} : Getting wifi messages for only single time-stamp. Converting into List.") - wifi_messages = [{f"{wifi_messages['resource']}.{wifi_messages['time-stamp']}": wifi_messages}] + logging.info( + f"Device {device_eid} : Getting wifi messages for only single time-stamp. Converting into List." + ) + wifi_messages = [ + { + f"{wifi_messages['resource']}.{wifi_messages['time-stamp']}": wifi_messages + } + ] # print("After Updating Wi-Fi msgs Response : ", wifi_messages) self.create_log_file(json_list=wifi_messages, file_name=file_name) - self.remove_files_with_duplicate_names(folder_path=f"{self.report_path}/Wifi_Messages/") + self.remove_files_with_duplicate_names( + folder_path=f"{self.report_path}/Wifi_Messages/" + ) message_keys = [] for index in range(len(wifi_messages)): @@ -381,15 +470,17 @@ def collect_device_metrics(self, device_metrics=None, device_eid=None, since_tim # print("Key list", message_keys) # android (flag) check for clustered lanforge cases is_android = False - adb_response = self.json_get_with_retry('/adb/') + adb_response = self.json_get_with_retry("/adb/") try: - adb_devices = adb_response['devices'] + adb_devices = adb_response["devices"] except (TypeError, KeyError) as e: logging.error( f"collect_device_metrics: LANforge response is not in expected format ({e}) while fetching " - f"/adb/ devices. Data received: {adb_response}") + f"/adb/ devices. Data received: {adb_response}" + ) logging.warning( - f"Could not fetch adb device list; relying only on the '1.1.' prefix heuristic for {device_eid}.") + f"Could not fetch adb device list; relying only on the '1.1.' prefix heuristic for {device_eid}." + ) adb_devices = [] for device_data in adb_devices: device_name, _ = list(device_data.keys())[0], list(device_data.values())[0] @@ -398,105 +489,202 @@ def collect_device_metrics(self, device_metrics=None, device_eid=None, since_tim break if "1.1." in device_eid or is_android: # disconnects - android_disconnect_count = self.count_wifi_msg_matches(wifi_messages=wifi_messages, message_keys=message_keys, - device_eid=device_eid, match_text="Terminating...") + android_disconnect_count = self.count_wifi_msg_matches( + wifi_messages=wifi_messages, + message_keys=message_keys, + device_eid=device_eid, + match_text="Terminating...", + ) if android_disconnect_count > 1 or android_disconnect_count == 0: device_state = self.utility.get_device_state(device=device_eid) - if device_state == 'COMPLETED': + if device_state == "COMPLETED": logging.info("The Device %s is in connected state." % device_eid) android_disconnect_count = 0 else: - logging.info("The Device %s is not in connected state." % device_eid) + logging.info( + "The Device %s is not in connected state." % device_eid + ) android_disconnect_count = 1 - logging.info(f"Disconnect Count For Android: {android_disconnect_count}") + logging.info( + f"Disconnect Count For Android: {android_disconnect_count}" + ) # Updating the dict with disconnects for android - logging.info("Final Disconnect count for %s: %s" % (device_eid, android_disconnect_count)) + logging.info( + "Final Disconnect count for %s: %s" + % (device_eid, android_disconnect_count) + ) device_metrics[device_eid]["Disconnected"] = android_disconnect_count # scanning count - android_scan_count = self.count_wifi_msg_matches(wifi_messages=wifi_messages, message_keys=message_keys, - device_eid=device_eid, match_text="SCAN-STARTED") - logging.info("Final Scanning Count for %s: %s" % (device_eid, android_scan_count)) + android_scan_count = self.count_wifi_msg_matches( + wifi_messages=wifi_messages, + message_keys=message_keys, + device_eid=device_eid, + match_text="SCAN-STARTED", + ) + logging.info( + "Final Scanning Count for %s: %s" % (device_eid, android_scan_count) + ) device_metrics[str(device_eid)]["Scanning"] = android_scan_count # association attempts - android_association_attempt = self.count_wifi_msg_matches(wifi_messages=wifi_messages, message_keys=message_keys, - device_eid=device_eid, match_text="ASSOCIATING") - logging.info("Final Association Attempts Count for %s: %s" % (device_eid, android_association_attempt)) - device_metrics[str(device_eid)]["ConnectAttempt"] = android_association_attempt + android_association_attempt = self.count_wifi_msg_matches( + wifi_messages=wifi_messages, + message_keys=message_keys, + device_eid=device_eid, + match_text="ASSOCIATING", + ) + logging.info( + "Final Association Attempts Count for %s: %s" + % (device_eid, android_association_attempt) + ) + device_metrics[str(device_eid)][ + "ConnectAttempt" + ] = android_association_attempt # association rejections - android_association_rejection = self.count_wifi_msg_matches(wifi_messages=wifi_messages, message_keys=message_keys, - device_eid=device_eid, match_text="ASSOC_REJECT") - logging.info("Final Association Rejection Count for %s: %s" % (device_eid, android_association_rejection)) - device_metrics[str(device_eid)]["Association Rejection"] = android_association_rejection + android_association_rejection = self.count_wifi_msg_matches( + wifi_messages=wifi_messages, + message_keys=message_keys, + device_eid=device_eid, + match_text="ASSOC_REJECT", + ) + logging.info( + "Final Association Rejection Count for %s: %s" + % (device_eid, android_association_rejection) + ) + device_metrics[str(device_eid)][ + "Association Rejection" + ] = android_association_rejection # connections - android_connected_count = self.count_wifi_msg_matches(wifi_messages=wifi_messages, message_keys=message_keys, - device_eid=device_eid, match_text="CTRL-EVENT-CONNECTED") + android_connected_count = self.count_wifi_msg_matches( + wifi_messages=wifi_messages, + message_keys=message_keys, + device_eid=device_eid, + match_text="CTRL-EVENT-CONNECTED", + ) # Double-checking & adding remarks if any if android_connected_count > 1 or android_connected_count == 0: device_ssid = self.utility.get_device_ssid(device=device_eid) if device_ssid == self.ssid: - logging.info("The Device %s is connected to expected ssid" % device_eid) + logging.info( + "The Device %s is connected to expected ssid" % device_eid + ) android_connected_count = 1 else: - logging.info("**** The Device is not connected to the expected ssid ****") + logging.info( + "**** The Device is not connected to the expected ssid ****" + ) android_connected_count = 0 logging.info(f"Connected Count for Android: {android_connected_count}") # Updating the dict with connects for android - logging.info("Final Connected Count for %s: %s" % (device_eid, android_connected_count)) + logging.info( + "Final Connected Count for %s: %s" + % (device_eid, android_connected_count) + ) device_metrics[str(device_eid)]["Connected"] = android_connected_count # Adding remarks remarks = "NA" device_metrics[str(device_eid)]["Remarks"] = remarks # Updating the association-rejections if android_association_attempt > android_connected_count: - android_association_rejection = android_association_attempt - android_connected_count - device_metrics[str(device_eid)]["Association Rejection"] = android_association_rejection + android_association_rejection = ( + android_association_attempt - android_connected_count + ) + device_metrics[str(device_eid)][ + "Association Rejection" + ] = android_association_rejection if android_connected_count > 0: - _, resource, serial = device_eid.split('.') - resource_id_response = self.json_get_with_retry('/adb/1/{}/{}?fields=resource-id'.format(resource, serial)) + _, resource, serial = device_eid.split(".") + resource_id_response = self.json_get_with_retry( + "/adb/1/{}/{}?fields=resource-id".format(resource, serial) + ) port_response = None try: - resource_id = resource_id_response['devices']['resource-id'] - port_response = self.json_get_with_retry('port/1/{}/wlan0?fields=cx time (us)'.format(resource_id.split('.')[1])) - cx_time_us = port_response['interface']['cx time (us)'] - device_metrics[str(device_eid)]['cx time (us)'] = cx_time_us + resource_id = resource_id_response["devices"]["resource-id"] + port_response = self.json_get_with_retry( + "port/1/{}/wlan0?fields=cx time (us)".format( + resource_id.split(".")[1] + ) + ) + cx_time_us = port_response["interface"]["cx time (us)"] + device_metrics[str(device_eid)]["cx time (us)"] = cx_time_us except (TypeError, KeyError) as e: logging.error( f"collect_device_metrics: could not fetch cx time (us) for device {device_eid}; LANforge " f"response is not in expected format ({e}). resource-id response: {resource_id_response}, " - f"port response: {port_response}") - device_metrics[str(device_eid)]['cx time (us)'] = 'NA' + f"port response: {port_response}" + ) + device_metrics[str(device_eid)]["cx time (us)"] = "NA" else: - device_metrics[str(device_eid)]['cx time (us)'] = 'NA' + device_metrics[str(device_eid)]["cx time (us)"] = "NA" else: if device_eid in self.windows_list: # for windows - win_disconnect_count = self.count_wifi_msg_matches(wifi_messages=wifi_messages, message_keys=message_keys, - device_eid=device_eid, match_text="Wireless security stopped.") + win_disconnect_count = self.count_wifi_msg_matches( + wifi_messages=wifi_messages, + message_keys=message_keys, + device_eid=device_eid, + match_text="Wireless security stopped.", + ) # Double-checking the disconnect count with another key msg if win_disconnect_count == 0: - win_disconnect_count = self.count_wifi_msg_matches(wifi_messages=wifi_messages, message_keys=message_keys, - device_eid=device_eid, - match_text="WLAN AutoConfig service has successfully disconnected from a wireless network") - logging.info("Final Disconnect count for %s: %s" % (device_eid, win_disconnect_count)) + win_disconnect_count = self.count_wifi_msg_matches( + wifi_messages=wifi_messages, + message_keys=message_keys, + device_eid=device_eid, + match_text="WLAN AutoConfig service has successfully disconnected from a wireless network", + ) + logging.info( + "Final Disconnect count for %s: %s" + % (device_eid, win_disconnect_count) + ) device_metrics[device_eid]["Disconnected"] = win_disconnect_count - win_scan_count = self.count_wifi_msg_matches(wifi_messages=wifi_messages, message_keys=message_keys, - device_eid=device_eid, match_text="service started") - logging.info("Final Scanning Count for %s: %s" % (device_eid, win_scan_count)) + win_scan_count = self.count_wifi_msg_matches( + wifi_messages=wifi_messages, + message_keys=message_keys, + device_eid=device_eid, + match_text="service started", + ) + logging.info( + "Final Scanning Count for %s: %s" % (device_eid, win_scan_count) + ) device_metrics[str(device_eid)]["Scanning"] = win_scan_count - win_association_attempt = self.count_wifi_msg_matches(wifi_messages=wifi_messages, message_keys=message_keys, - device_eid=device_eid, match_text="association started.") - logging.info("Final Association Attempts Count for %s: %s" % (device_eid, win_association_attempt)) - device_metrics[str(device_eid)]["ConnectAttempt"] = win_association_attempt - win_association_rejection = self.count_wifi_msg_matches(wifi_messages=wifi_messages, message_keys=message_keys, - device_eid=device_eid, match_text="failed to connect") - logging.info("Final Association Rejection Count for %s: %s" % (device_eid, win_association_rejection)) - device_metrics[str(device_eid)]["Association Rejection"] = win_association_rejection - win_connected_count = self.count_wifi_msg_matches(wifi_messages=wifi_messages, message_keys=message_keys, - device_eid=device_eid, match_text="connected") + win_association_attempt = self.count_wifi_msg_matches( + wifi_messages=wifi_messages, + message_keys=message_keys, + device_eid=device_eid, + match_text="association started.", + ) + logging.info( + "Final Association Attempts Count for %s: %s" + % (device_eid, win_association_attempt) + ) + device_metrics[str(device_eid)][ + "ConnectAttempt" + ] = win_association_attempt + win_association_rejection = self.count_wifi_msg_matches( + wifi_messages=wifi_messages, + message_keys=message_keys, + device_eid=device_eid, + match_text="failed to connect", + ) + logging.info( + "Final Association Rejection Count for %s: %s" + % (device_eid, win_association_rejection) + ) + device_metrics[str(device_eid)][ + "Association Rejection" + ] = win_association_rejection + win_connected_count = self.count_wifi_msg_matches( + wifi_messages=wifi_messages, + message_keys=message_keys, + device_eid=device_eid, + match_text="connected", + ) win_connection_state_unverified = False # assoc-rejection based logic if win_association_rejection: # Updating the connects - actual_connects = win_association_attempt - win_association_rejection + actual_connects = ( + win_association_attempt - win_association_rejection + ) if actual_connects == win_connected_count: win_connected_count = win_connected_count else: @@ -508,9 +696,14 @@ def collect_device_metrics(self, device_metrics=None, device_eid=None, since_tim # Double-checking if win_connected_count > 1 or win_connected_count == 0: eid_parts = device_eid.split(".") - port_response = self.json_get_with_retry(f"port/{eid_parts[0]}/{eid_parts[1]}/{eid_parts[2]}?fields=ssid,ip") + port_response = self.json_get_with_retry( + f"port/{eid_parts[0]}/{eid_parts[1]}/{eid_parts[2]}?fields=ssid,ip" + ) try: - if port_response['interface']['ssid'] == self.ssid and port_response['interface']['ip'] != "0.0.0.0": + if ( + port_response["interface"]["ssid"] == self.ssid + and port_response["interface"]["ip"] != "0.0.0.0" + ): win_connected_count = 1 else: win_connected_count = 0 @@ -518,15 +711,23 @@ def collect_device_metrics(self, device_metrics=None, device_eid=None, since_tim logging.error( f"collect_device_metrics: could not verify connection state for device " f"{device_eid}; LANforge response is not in expected format ({e}). Data " - f"received: {port_response}") + f"received: {port_response}" + ) win_connected_count = 0 win_connection_state_unverified = True - logging.info("Final Connected Count for %s: %s" % (device_eid, win_connected_count)) + logging.info( + "Final Connected Count for %s: %s" + % (device_eid, win_connected_count) + ) device_metrics[str(device_eid)]["Connected"] = win_connected_count # Updating the association-rejections if win_association_attempt > win_connected_count: - win_association_rejection = win_association_attempt - win_connected_count - device_metrics[str(device_eid)]["Association Rejection"] = win_association_rejection + win_association_rejection = ( + win_association_attempt - win_connected_count + ) + device_metrics[str(device_eid)][ + "Association Rejection" + ] = win_association_rejection # Adding re-marks remarks = "NA" if win_disconnect_count == 0 and win_connected_count == 1: @@ -538,47 +739,91 @@ def collect_device_metrics(self, device_metrics=None, device_eid=None, since_tim device_metrics[str(device_eid)]["Remarks"] = remarks if win_connected_count > 0: eid_parts = device_eid.split(".") - port_response = self.json_get_with_retry(f"port/{eid_parts[0]}/{eid_parts[1]}/{eid_parts[2]}?fields=cx time (us)") + port_response = self.json_get_with_retry( + f"port/{eid_parts[0]}/{eid_parts[1]}/{eid_parts[2]}?fields=cx time (us)" + ) try: - cx_time_us = port_response['interface']['cx time (us)'] - device_metrics[str(device_eid)]['cx time (us)'] = cx_time_us + cx_time_us = port_response["interface"]["cx time (us)"] + device_metrics[str(device_eid)]["cx time (us)"] = cx_time_us except (TypeError, KeyError) as e: logging.error( f"collect_device_metrics: could not fetch cx time (us) for device {device_eid}; " - f"LANforge response is not in expected format ({e}). Data received: {port_response}") - device_metrics[str(device_eid)]['cx time (us)'] = 'NA' + f"LANforge response is not in expected format ({e}). Data received: {port_response}" + ) + device_metrics[str(device_eid)]["cx time (us)"] = "NA" else: - device_metrics[str(device_eid)]['cx time (us)'] = 'NA' + device_metrics[str(device_eid)]["cx time (us)"] = "NA" else: # other means (for linux, mac) - linux_mac_disconnect_count = self.count_wifi_msg_matches(wifi_messages=wifi_messages, message_keys=message_keys, - device_eid=device_eid, match_text="disconnected") + linux_mac_disconnect_count = self.count_wifi_msg_matches( + wifi_messages=wifi_messages, + message_keys=message_keys, + device_eid=device_eid, + match_text="disconnected", + ) # Double-checking the disconnect count with another key msg if linux_mac_disconnect_count == 0: - linux_mac_disconnect_count = self.count_wifi_msg_matches(wifi_messages=wifi_messages, message_keys=message_keys, - device_eid=device_eid, - match_text="<3>CTRL-EVENT-DSCP-POLICY clear_all") - logging.info("Final Disconnect count for %s: %s" % (device_eid, linux_mac_disconnect_count)) + linux_mac_disconnect_count = self.count_wifi_msg_matches( + wifi_messages=wifi_messages, + message_keys=message_keys, + device_eid=device_eid, + match_text="<3>CTRL-EVENT-DSCP-POLICY clear_all", + ) + logging.info( + "Final Disconnect count for %s: %s" + % (device_eid, linux_mac_disconnect_count) + ) device_metrics[device_eid]["Disconnected"] = linux_mac_disconnect_count - linux_mac_scan_count = self.count_wifi_msg_matches(wifi_messages=wifi_messages, message_keys=message_keys, - device_eid=device_eid, match_text="<3>CTRL-EVENT-SCAN-STARTED") - logging.info("Final Scanning Count for %s: %s" % (device_eid, linux_mac_scan_count)) + linux_mac_scan_count = self.count_wifi_msg_matches( + wifi_messages=wifi_messages, + message_keys=message_keys, + device_eid=device_eid, + match_text="<3>CTRL-EVENT-SCAN-STARTED", + ) + logging.info( + "Final Scanning Count for %s: %s" + % (device_eid, linux_mac_scan_count) + ) device_metrics[str(device_eid)]["Scanning"] = linux_mac_scan_count - linux_mac_association_attempt = self.count_wifi_msg_matches(wifi_messages=wifi_messages, message_keys=message_keys, - device_eid=device_eid, match_text="<3>Trying to associate with") - logging.info("Final Association Attempts Count for %s: %s" % (device_eid, linux_mac_association_attempt)) - device_metrics[str(device_eid)]["ConnectAttempt"] = linux_mac_association_attempt - linux_mac_association_rejection = self.count_wifi_msg_matches(wifi_messages=wifi_messages, message_keys=message_keys, - device_eid=device_eid, match_text="NoneValue") - logging.info("Final Association Rejection Count for %s: %s" % (device_eid, linux_mac_association_rejection)) - device_metrics[str(device_eid)]["Association Rejection"] = linux_mac_association_rejection - - linux_mac_connected_count = self.count_wifi_msg_matches(wifi_messages=wifi_messages, message_keys=message_keys, - device_eid=device_eid, match_text="<3>CTRL-EVENT-CONNECTED") + linux_mac_association_attempt = self.count_wifi_msg_matches( + wifi_messages=wifi_messages, + message_keys=message_keys, + device_eid=device_eid, + match_text="<3>Trying to associate with", + ) + logging.info( + "Final Association Attempts Count for %s: %s" + % (device_eid, linux_mac_association_attempt) + ) + device_metrics[str(device_eid)][ + "ConnectAttempt" + ] = linux_mac_association_attempt + linux_mac_association_rejection = self.count_wifi_msg_matches( + wifi_messages=wifi_messages, + message_keys=message_keys, + device_eid=device_eid, + match_text="NoneValue", + ) + logging.info( + "Final Association Rejection Count for %s: %s" + % (device_eid, linux_mac_association_rejection) + ) + device_metrics[str(device_eid)][ + "Association Rejection" + ] = linux_mac_association_rejection + + linux_mac_connected_count = self.count_wifi_msg_matches( + wifi_messages=wifi_messages, + message_keys=message_keys, + device_eid=device_eid, + match_text="<3>CTRL-EVENT-CONNECTED", + ) linux_mac_connection_state_unverified = False # assoc-rejection based logic if linux_mac_association_rejection: # Updating the connects - actual_connects = linux_mac_association_attempt - linux_mac_association_rejection + actual_connects = ( + linux_mac_association_attempt - linux_mac_association_rejection + ) if actual_connects == linux_mac_connected_count: linux_mac_connected_count = linux_mac_connected_count else: @@ -588,11 +833,19 @@ def collect_device_metrics(self, device_metrics=None, device_eid=None, since_tim linux_mac_connected_count = linux_mac_connected_count else: # Double-checking & adding remarks if any - if linux_mac_connected_count > 1 or linux_mac_connected_count == 0: + if ( + linux_mac_connected_count > 1 + or linux_mac_connected_count == 0 + ): eid_parts = device_eid.split(".") - port_response = self.json_get_with_retry(f"port/{eid_parts[0]}/{eid_parts[1]}/{eid_parts[2]}?fields=ssid,ip") + port_response = self.json_get_with_retry( + f"port/{eid_parts[0]}/{eid_parts[1]}/{eid_parts[2]}?fields=ssid,ip" + ) try: - if port_response['interface']['ssid'] == self.ssid and port_response['interface']['ip'] != "0.0.0.0": + if ( + port_response["interface"]["ssid"] == self.ssid + and port_response["interface"]["ip"] != "0.0.0.0" + ): linux_mac_connected_count = 1 else: linux_mac_connected_count = 0 @@ -600,15 +853,23 @@ def collect_device_metrics(self, device_metrics=None, device_eid=None, since_tim logging.error( f"collect_device_metrics: could not verify connection state for device " f"{device_eid}; LANforge response is not in expected format ({e}). Data " - f"received: {port_response}") + f"received: {port_response}" + ) linux_mac_connected_count = 0 linux_mac_connection_state_unverified = True - logging.info("Final Connected Count for %s: %s" % (device_eid, linux_mac_connected_count)) + logging.info( + "Final Connected Count for %s: %s" + % (device_eid, linux_mac_connected_count) + ) device_metrics[str(device_eid)]["Connected"] = linux_mac_connected_count # Updating the association-rejections if linux_mac_association_attempt > linux_mac_connected_count: - linux_mac_association_rejection = linux_mac_association_attempt - linux_mac_connected_count - device_metrics[str(device_eid)]["Association Rejection"] = linux_mac_association_rejection + linux_mac_association_rejection = ( + linux_mac_association_attempt - linux_mac_connected_count + ) + device_metrics[str(device_eid)][ + "Association Rejection" + ] = linux_mac_association_rejection # Adding remarks remarks = "NA" if linux_mac_disconnect_count == 0 and linux_mac_connected_count == 1: @@ -620,17 +881,20 @@ def collect_device_metrics(self, device_metrics=None, device_eid=None, since_tim device_metrics[str(device_eid)]["Remarks"] = remarks if linux_mac_connected_count > 0: eid_parts = device_eid.split(".") - port_response = self.json_get_with_retry(f"port/{eid_parts[0]}/{eid_parts[1]}/{eid_parts[2]}?fields=cx time (us)") + port_response = self.json_get_with_retry( + f"port/{eid_parts[0]}/{eid_parts[1]}/{eid_parts[2]}?fields=cx time (us)" + ) try: - cx_time_us = port_response['interface']['cx time (us)'] - device_metrics[str(device_eid)]['cx time (us)'] = cx_time_us + cx_time_us = port_response["interface"]["cx time (us)"] + device_metrics[str(device_eid)]["cx time (us)"] = cx_time_us except (TypeError, KeyError) as e: logging.error( f"collect_device_metrics: could not fetch cx time (us) for device {device_eid}; " - f"LANforge response is not in expected format ({e}). Data received: {port_response}") - device_metrics[str(device_eid)]['cx time (us)'] = 'NA' + f"LANforge response is not in expected format ({e}). Data received: {port_response}" + ) + device_metrics[str(device_eid)]["cx time (us)"] = "NA" else: - device_metrics[str(device_eid)]['cx time (us)'] = 'NA' + device_metrics[str(device_eid)]["cx time (us)"] = "NA" logging.info("device_metrics " + str(device_metrics)) self.write_iteration_csvs(device_metrics, iteration) @@ -658,52 +922,78 @@ def aggregate_device_metrics(self, per_iteration_results): else: if metric_name not in aggregated_metrics[device_eid]: aggregated_metrics[device_eid][metric_name] = 0 - aggregated_metrics[device_eid][metric_name] += int(value) if str(value).isdigit() else 0 + aggregated_metrics[device_eid][metric_name] += ( + int(value) if str(value).isdigit() else 0 + ) return dict(aggregated_metrics) def write_coordinate_csv(self, per_iteration_results, iteration): - columns = ['Client', 'ConnectAttempt', 'Disconnected', 'Scanning', 'Association Rejection', 'Connected', 'Iterations', 'Status', 'coordinate'] + columns = [ + "Client", + "ConnectAttempt", + "Disconnected", + "Scanning", + "Association Rejection", + "Connected", + "Iterations", + "Status", + "coordinate", + ] if self.rotation_enabled: - columns.append('angle') + columns.append("angle") if self.rotation_enabled: client_suffix = f"_{self.current_coordinate}_{self.current_angle}" else: client_suffix = f"_{self.current_coordinate}" - aggregated_metrics = self.aggregate_device_metrics(per_iteration_results=per_iteration_results) + aggregated_metrics = self.aggregate_device_metrics( + per_iteration_results=per_iteration_results + ) if self.current_coordinate not in self.coordinate_df: self.coordinate_df[self.current_coordinate] = {} df = pd.DataFrame(columns=columns) for device_eid, metrics in aggregated_metrics.items(): client_name = f"{device_eid}{client_suffix}" self.coordinate_df[self.current_coordinate][client_name] = metrics.copy() - self.coordinate_df[self.current_coordinate][client_name]["coordinate"] = self.current_coordinate - self.coordinate_df[self.current_coordinate][client_name]["Status"] = "running" + self.coordinate_df[self.current_coordinate][client_name][ + "coordinate" + ] = self.current_coordinate + self.coordinate_df[self.current_coordinate][client_name][ + "Status" + ] = "running" if self.rotation_enabled: - self.coordinate_df[self.current_coordinate][client_name]["angle"] = self.current_angle + self.coordinate_df[self.current_coordinate][client_name][ + "angle" + ] = self.current_angle rows = [] for client_name, metrics in self.coordinate_df[self.current_coordinate].items(): row = { - 'Client': client_name, - 'ConnectAttempt': metrics.get('ConnectAttempt', 0), - 'Disconnected': metrics.get('Disconnected', 0), - 'Scanning': metrics.get('Scanning', 0), - 'Association Rejection': metrics.get('Association Rejection', 0), - 'Connected': metrics.get('Connected', 0), - 'Iterations': iteration + 1, - 'Status': metrics.get('Status', 'NA'), - 'coordinate': metrics.get('coordinate', 'NA') + "Client": client_name, + "ConnectAttempt": metrics.get("ConnectAttempt", 0), + "Disconnected": metrics.get("Disconnected", 0), + "Scanning": metrics.get("Scanning", 0), + "Association Rejection": metrics.get("Association Rejection", 0), + "Connected": metrics.get("Connected", 0), + "Iterations": iteration + 1, + "Status": metrics.get("Status", "NA"), + "coordinate": metrics.get("coordinate", "NA"), } if self.rotation_enabled: - row['angle'] = metrics.get('angle', 'NA') + row["angle"] = metrics.get("angle", "NA") rows.append(row) df = pd.DataFrame(rows, columns=columns) self.result_df = df.copy() - df.to_csv(f"{self.report_path}/overall_reset_{self.current_coordinate}.csv", index=False) + df.to_csv( + f"{self.report_path}/overall_reset_{self.current_coordinate}.csv", + index=False, + ) if self.dowebgui: - df.to_csv(f"{self.result_dir}/overall_reset_{self.current_coordinate}.csv", index=False) + df.to_csv( + f"{self.result_dir}/overall_reset_{self.current_coordinate}.csv", + index=False, + ) def performing_resets(self, test_start_time=None): iteration_indexes = [] @@ -727,7 +1017,9 @@ def performing_resets(self, test_start_time=None): break if paused: # After charging, return to the last coordinate - reached, abort = self.robot_obj.move_to_coordinate(self.current_coordinate) + reached, abort = self.robot_obj.move_to_coordinate( + self.current_coordinate + ) # If user stopped the test during movement if abort: test_stopped_by_user = True @@ -741,8 +1033,12 @@ def performing_resets(self, test_start_time=None): test_stopped_by_user = True break next_battery_check = current_time + battery_check_interval_sec - logging.info(f"Waiting until given {self.reset_interval_sec} sec time interval to finish...") - time.sleep(int(self.reset_interval_sec)) # sleeping until time interval finish + logging.info( + f"Waiting until given {self.reset_interval_sec} sec time interval to finish..." + ) + time.sleep( + int(self.reset_interval_sec) + ) # sleeping until time interval finish logging.info(f"Iteration :- {iteration}") logging.info("Reset -" + str(iteration)) device_metrics = dict.fromkeys(self.adb_device_list) @@ -751,13 +1047,23 @@ def performing_resets(self, test_start_time=None): logging.info(f"local dict for laptops : {laptop_metrics}") device_metrics.update(laptop_metrics) - metric_names = ["ConnectAttempt", "Disconnected", "Scanning", "Association Rejection", "Connected"] + metric_names = [ + "ConnectAttempt", + "Disconnected", + "Scanning", + "Association Rejection", + "Connected", + ] empty_metrics = dict.fromkeys(metric_names) for device_eid in self.adb_device_list: - device_metrics[device_eid] = empty_metrics.copy() # for android devices dict + device_metrics[device_eid] = ( + empty_metrics.copy() + ) # for android devices dict for device_eid in self.all_laptops: - laptop_metrics[device_eid] = empty_metrics.copy() # for laptop devices dict + laptop_metrics[device_eid] = ( + empty_metrics.copy() + ) # for laptop devices dict logging.info(f"Final Outcome dict for android devices: {device_metrics}") logging.info(f"Final Outcome dict for laptop devices: {laptop_metrics}") logging.info(str(device_metrics)) @@ -794,67 +1100,91 @@ def performing_resets(self, test_start_time=None): logging.info("FAILED : MAY BE NOT ALL STATIONS ACQUIRED IP'S") time.sleep(30) for device_eid in self.all_selected_devices: - iteration_metrics = self.collect_device_metrics(device_metrics=device_metrics, device_eid=device_eid, - since_time=since_time, - file_name=f"reset_{iteration}_log.json", - iteration=iteration) + iteration_metrics = self.collect_device_metrics( + device_metrics=device_metrics, + device_eid=device_eid, + since_time=since_time, + file_name=f"reset_{iteration}_log.json", + iteration=iteration, + ) per_iteration_results[iteration] = iteration_metrics if self.robot_test: - self.write_coordinate_csv(per_iteration_results=per_iteration_results, iteration=iteration) + self.write_coordinate_csv( + per_iteration_results=per_iteration_results, iteration=iteration + ) else: self.write_overall_csv(per_iteration_results) if self.dowebgui: - with open(self.result_dir + f"/../../Running_instances/{self.lanforge_ip}_{self.test_name}_running.json", - 'r') as file: + with open( + self.result_dir + + f"/../../Running_instances/{self.lanforge_ip}_{self.test_name}_running.json", + "r", + ) as file: run_status = json.load(file) if run_status["status"] != "Running": - logging.info('Test is stopped by the user') + logging.info("Test is stopped by the user") test_stopped = True self.robo_test_stopped = True break - logging.info('{}'.format(per_iteration_results)) + logging.info("{}".format(per_iteration_results)) if test_stopped: stopped_metrics = { - 'ConnectAttempt': 0, - 'Disconnected': 0, - 'Scanning': 0, - 'Association Rejection': 0, - 'Connected': 0, - 'Remarks': "Test stopped by user", - 'cx time (us)': 0 + "ConnectAttempt": 0, + "Disconnected": 0, + "Scanning": 0, + "Association Rejection": 0, + "Connected": 0, + "Remarks": "Test stopped by user", + "cx time (us)": 0, } empty_iterations = [] for iteration_index in range(self.iterations): if per_iteration_results.get(iteration_index) is None: empty_iterations.append(iteration_index) else: - for device_eid, metrics in per_iteration_results[iteration_index].items(): + for device_eid, metrics in per_iteration_results[ + iteration_index + ].items(): if any(value is None for value in metrics.values()): - per_iteration_results[iteration_index][device_eid] = stopped_metrics.copy() + per_iteration_results[iteration_index][ + device_eid + ] = stopped_metrics.copy() for iteration_index in empty_iterations: del per_iteration_results[iteration_index] break - logging.info(f"Final Reset Count Dictionary for all clients: {per_iteration_results}") + logging.info( + f"Final Reset Count Dictionary for all clients: {per_iteration_results}" + ) logging.info("reset dict " + str(per_iteration_results)) test_end = datetime.now() test_end_time = test_end.strftime("%b %d %H:%M:%S") if self.robot_test: if self.rotation_enabled: - logging.info(f"At coordinate {self.current_coordinate} on Angle {self.current_angle} Test Ended at {test_end}") + logging.info( + f"At coordinate {self.current_coordinate} on Angle {self.current_angle} Test Ended at {test_end}" + ) else: - logging.info(f"At coordinate {self.current_coordinate} Test Ended at {test_end}") + logging.info( + f"At coordinate {self.current_coordinate} Test Ended at {test_end}" + ) else: logging.info(f"Test Ended at {test_end}") # logging.info("Test ended at " + test_end_time) - time_format = '%b %d %H:%M:%S' - test_duration = datetime.strptime(test_end_time, time_format) - datetime.strptime(test_start_time, time_format) + time_format = "%b %d %H:%M:%S" + test_duration = datetime.strptime( + test_end_time, time_format + ) - datetime.strptime(test_start_time, time_format) if self.robot_test: if self.rotation_enabled: - logging.info(f"Total Test Duration taken to complete port resets at coordinate {self.current_coordinate} on angle {self.current_angle}: {test_duration}") + logging.info( + f"Total Test Duration taken to complete port resets at coordinate {self.current_coordinate} on angle {self.current_angle}: {test_duration}" + ) else: - logging.info(f"Total Test Duration taken to complete port resets at coordinate {self.current_coordinate} : {test_duration}") + logging.info( + f"Total Test Duration taken to complete port resets at coordinate {self.current_coordinate} : {test_duration}" + ) else: logging.info(f"Total Test Duration: {test_duration}") @@ -867,47 +1197,86 @@ def run(self): test_start = datetime.now() test_start_time = test_start.strftime("%b %d %H:%M:%S") logging.info(f"Test Started at {test_start}") - self.adb_device_list = self.interop.check_sdk_release(selected_android_devices=self.final_selected_android_list) + self.adb_device_list = self.interop.check_sdk_release( + selected_android_devices=self.final_selected_android_list + ) self.windows_list = self.base_interop_profile.windows_list self.linux_list = self.base_interop_profile.linux_list self.mac_list = self.base_interop_profile.mac_list - logging.info(f"Final Active Devices List (Android, Windows, Linux, Mac) Which support user specified release & not in phantom : {self.adb_device_list, self.base_interop_profile.windows_list, self.base_interop_profile.linux_list, self.base_interop_profile.mac_list}") # noqa: E501 - self.all_selected_devices = self.adb_device_list + self.windows_list + self.linux_list + self.mac_list + logging.info( + f"Final Active Devices List (Android, Windows, Linux, Mac) Which support user specified release & not in phantom : {self.adb_device_list, self.base_interop_profile.windows_list, self.base_interop_profile.linux_list, self.base_interop_profile.mac_list}" # noqa: E501 + ) + self.all_selected_devices = ( + self.adb_device_list + + self.windows_list + + self.linux_list + + self.mac_list + ) self.all_laptops = self.windows_list + self.linux_list + self.mac_list logging.info(f"All Selected Devices: {self.all_selected_devices}") logging.info(f"All Active Laptop Devices {self.all_laptops}") logging.info( - f"The total number of available active & supported sdk release android devices are: {len(self.adb_device_list)}") + f"The total number of available active & supported sdk release android devices are: {len(self.adb_device_list)}" + ) logging.info( - f"The total number of available active windows devices are: {len(self.base_interop_profile.windows_list)}") + f"The total number of available active windows devices are: {len(self.base_interop_profile.windows_list)}" + ) logging.info( - f"The total number of available active Linux devices are: {len(self.base_interop_profile.linux_list)}") + f"The total number of available active Linux devices are: {len(self.base_interop_profile.linux_list)}" + ) logging.info( - f"The total number of available active Mac devices are: {len(self.base_interop_profile.mac_list)}") + f"The total number of available active Mac devices are: {len(self.base_interop_profile.mac_list)}" + ) - if len(self.adb_device_list) == 0 and len(self.base_interop_profile.windows_list) == 0 and len(self.base_interop_profile.linux_list) == 0 and len(self.base_interop_profile.mac_list) == 0: + if ( + len(self.adb_device_list) == 0 + and len(self.base_interop_profile.windows_list) == 0 + and len(self.base_interop_profile.linux_list) == 0 + and len(self.base_interop_profile.mac_list) == 0 + ): logging.info("There is no active devices please check system.") - logging.info('Aborting the test.') + logging.info("Aborting the test.") # Added for the purpose to stop webui test when there are no selected devices availble in lanforge. raise RuntimeError("There is no active devices please check system.") else: for index in range(len(self.adb_device_list)): - self.android_serials.append(self.adb_device_list[index].split(".")[2]) - logging.info(f"Separated device names from the full name: {self.android_serials}") + self.android_serials.append( + self.adb_device_list[index].split(".")[2] + ) + logging.info( + f"Separated device names from the full name: {self.android_serials}" + ) # check status of devices phantom_states = [] for device_eid in self.adb_device_list: - phantom_states.append(self.interop.get_device_details(device=device_eid, query="phantom")) - if self.adb_device_list or self.windows_list or self.linux_list or self.mac_list: + phantom_states.append( + self.interop.get_device_details(device=device_eid, query="phantom") + ) + if ( + self.adb_device_list + or self.windows_list + or self.linux_list + or self.mac_list + ): for device_eid in self.adb_device_list: - self.android_user_names.append(self.interop.get_device_details(device=device_eid, query="user-name")) - logging.info(f"ADB user-names for selected devices: {self.android_user_names}") + self.android_user_names.append( + self.interop.get_device_details( + device=device_eid, query="user-name" + ) + ) + logging.info( + f"ADB user-names for selected devices: {self.android_user_names}" + ) logging.info("Checking heath data...") android_health = dict.fromkeys(self.adb_device_list) - logging.info(f"Initial Health Data For Android Clients: {android_health}") + logging.info( + f"Initial Health Data For Android Clients: {android_health}" + ) laptop_health = dict.fromkeys(self.all_laptops) - logging.info(f"Initial Health Data For Laptops Clients: {laptop_health}") + logging.info( + f"Initial Health Data For Laptops Clients: {laptop_health}" + ) # pre-checking whether the adb device connected to given ssid or not for device_eid in self.adb_device_list: @@ -916,41 +1285,69 @@ def run(self): logging.info("Phone %s is in connected state." % device_eid) device_ssid = self.utility.get_device_ssid(device=device_eid) if device_ssid == self.ssid: - logging.info("The Device %s is connected to expected ssid (%s)" % (device_eid, device_ssid)) - android_health[device_eid] = self.utility.get_wifi_health_monitor(device=device_eid, ssid=self.ssid) + logging.info( + "The Device %s is connected to expected ssid (%s)" + % (device_eid, device_ssid) + ) + android_health[device_eid] = ( + self.utility.get_wifi_health_monitor( + device=device_eid, ssid=self.ssid + ) + ) else: - logging.info("**** The Device is not connected to the expected ssid ****") + logging.info( + "**** The Device is not connected to the expected ssid ****" + ) else: logging.info("Waiting for 30 sec & Checking again") time.sleep(30) device_state = self.utility.get_device_state(device=device_eid) - logging.info("Checking Device Status Again..." + str(device_state)) + logging.info( + "Checking Device Status Again..." + str(device_state) + ) logging.info(f"Device state {device_state}") if device_state == "COMPLETED,": logging.info("Phone is in connected state") - device_ssid = self.utility.get_device_ssid(device=device_eid) + device_ssid = self.utility.get_device_ssid( + device=device_eid + ) if device_ssid == self.ssid: - logging.info("The Device %s is connected to expected ssid (%s)" % (device_eid, device_ssid)) - android_health[device_eid] = self.utility.get_wifi_health_monitor(device=device_eid, ssid=self.ssid) + logging.info( + "The Device %s is connected to expected ssid (%s)" + % (device_eid, device_ssid) + ) + android_health[device_eid] = ( + self.utility.get_wifi_health_monitor( + device=device_eid, ssid=self.ssid + ) + ) else: logging.info(f"device state {device_state}") - android_health[device_eid] = {'ConnectAttempt': '0', 'ConnectFailure': '0', 'AssocRej': '0', - 'AssocTimeout': '0'} + android_health[device_eid] = { + "ConnectAttempt": "0", + "ConnectFailure": "0", + "AssocRej": "0", + "AssocTimeout": "0", + } logging.info(f"Health Status for the Android Devices: {android_health}") logging.info(f"Health Status for the Laptop Devices: {laptop_health}") # Resting Starts from here if not self.robot_test: - per_iteration_results, test_duration = self.performing_resets(test_start_time=test_start_time) + per_iteration_results, test_duration = self.performing_resets( + test_start_time=test_start_time + ) return per_iteration_results, test_duration # For robot Scenario - if (self.rotation_list[0] != ""): + if self.rotation_list[0] != "": self.rotation_enabled = True self.robot_obj = RobotClass() self.robot_obj.robo_ip = self.robot_ip base_dir = os.path.dirname(os.path.dirname(self.result_dir)) - nav_data = os.path.join(base_dir, 'nav_data.json') # To generate nav_data.json in webgui folder + nav_data = os.path.join( + base_dir, "nav_data.json" + ) # To generate nav_data.json in webgui folder self.robot_obj.nav_data_path = nav_data self.robot_obj.create_waypointlist() self.robot_obj.ip = self.lanforge_ip @@ -965,15 +1362,24 @@ def run(self): # If test is stopped by user during battery wait if test_stopped_by_user: break - reached_coordinate, abort = self.robot_obj.move_to_coordinate(self.coordinate_list[coordinate_index]) + reached_coordinate, abort = self.robot_obj.move_to_coordinate( + self.coordinate_list[coordinate_index] + ) # If robot failed to reach the coordinate if abort: break if reached_coordinate: self.current_coordinate = self.coordinate_list[coordinate_index] if not self.rotation_enabled: - per_iteration_results, test_duration = self.performing_resets(test_start_time=test_start_time) - self.port_reset_data[self.coordinate_list[coordinate_index]] = {'per_iteration_results': per_iteration_results, 'test_duration': test_duration} + per_iteration_results, test_duration = ( + self.performing_resets(test_start_time=test_start_time) + ) + self.port_reset_data[ + self.coordinate_list[coordinate_index] + ] = { + "per_iteration_results": per_iteration_results, + "test_duration": test_duration, + } time.sleep(10) else: for angle_index in range(len(self.rotation_list)): @@ -981,15 +1387,32 @@ def run(self): if self.robo_test_stopped or test_stopped_by_user: break # Check for battery status before rotating to next angle - _, test_stopped_by_user = self.robot_obj.wait_for_battery() - rotated = self.robot_obj.rotate_angle(self.rotation_list[angle_index]) + _, test_stopped_by_user = ( + self.robot_obj.wait_for_battery() + ) + rotated = self.robot_obj.rotate_angle( + self.rotation_list[angle_index] + ) if rotated: self.current_angle = self.rotation_list[angle_index] - per_iteration_results, test_duration = self.performing_resets(test_start_time=test_start_time) - if self.coordinate_list[coordinate_index] not in self.port_reset_data: - self.port_reset_data[self.coordinate_list[coordinate_index]] = {} - self.port_reset_data[self.coordinate_list[coordinate_index]][self.rotation_list[angle_index]] = { - 'per_iteration_results': per_iteration_results, 'test_duration': test_duration} + per_iteration_results, test_duration = ( + self.performing_resets( + test_start_time=test_start_time + ) + ) + if ( + self.coordinate_list[coordinate_index] + not in self.port_reset_data + ): + self.port_reset_data[ + self.coordinate_list[coordinate_index] + ] = {} + self.port_reset_data[ + self.coordinate_list[coordinate_index] + ][self.rotation_list[angle_index]] = { + "per_iteration_results": per_iteration_results, + "test_duration": test_duration, + } time.sleep(10) if test_stopped_by_user or self.robo_test_stopped: @@ -998,13 +1421,32 @@ def run(self): except Exception as e: logger.error(str(e)) - def generate_overall_graph(self, per_iteration_results=None, figsize=(13, 5), _alignment=None, remove_border=None, - bar_width=0.7, _legend_handles=None, _legend_loc="best", _legend_box=None, - _legend_ncol=1, - _legend_fontsize=None, text_font=12, bar_text_rotation=45, graph_suffix=""): - metric_labels = ['Port Resets', 'Disconnected', 'Scans', 'Assoc Attempts', "Association Rejection", 'Connected'] + def generate_overall_graph( + self, + per_iteration_results=None, + figsize=(13, 5), + _alignment=None, + remove_border=None, + bar_width=0.7, + _legend_handles=None, + _legend_loc="best", + _legend_box=None, + _legend_ncol=1, + _legend_fontsize=None, + text_font=12, + bar_text_rotation=45, + graph_suffix="", + ): + metric_labels = [ + "Port Resets", + "Disconnected", + "Scans", + "Assoc Attempts", + "Association Rejection", + "Connected", + ] metric_totals = dict.fromkeys(metric_labels) - metric_totals['Port Resets'] = self.iterations * len(self.all_selected_devices) + metric_totals["Port Resets"] = self.iterations * len(self.all_selected_devices) connected_counts, laptop_connected_counts = [], [] disconnected_counts, laptop_disconnected_counts = [], [] @@ -1017,11 +1459,23 @@ def generate_overall_graph(self, per_iteration_results=None, figsize=(13, 5), _a disconnected, scanning, assoc_attempts, assoc_rejections = [], [], [], [] for iteration in per_iteration_results: if device_eid in list(per_iteration_results[iteration].keys()): - connected.append(per_iteration_results[iteration][device_eid]['Connected']) - disconnected.append(per_iteration_results[iteration][device_eid]['Disconnected']) - scanning.append(per_iteration_results[iteration][device_eid]['Scanning']) - assoc_attempts.append(per_iteration_results[iteration][device_eid]['ConnectAttempt']) - assoc_rejections.append(per_iteration_results[iteration][device_eid]["Association Rejection"]) + connected.append( + per_iteration_results[iteration][device_eid]["Connected"] + ) + disconnected.append( + per_iteration_results[iteration][device_eid]["Disconnected"] + ) + scanning.append( + per_iteration_results[iteration][device_eid]["Scanning"] + ) + assoc_attempts.append( + per_iteration_results[iteration][device_eid]["ConnectAttempt"] + ) + assoc_rejections.append( + per_iteration_results[iteration][device_eid][ + "Association Rejection" + ] + ) connected_counts.append(connected) disconnected_counts.append(disconnected) @@ -1034,11 +1488,23 @@ def generate_overall_graph(self, per_iteration_results=None, figsize=(13, 5), _a disconnected, scanning, assoc_attempts, assoc_rejections = [], [], [], [] for iteration in per_iteration_results: if device_eid in list(per_iteration_results[iteration].keys()): - connected.append(per_iteration_results[iteration][device_eid]['Connected']) - disconnected.append(per_iteration_results[iteration][device_eid]['Disconnected']) - scanning.append(per_iteration_results[iteration][device_eid]['Scanning']) - assoc_attempts.append(per_iteration_results[iteration][device_eid]['ConnectAttempt']) - assoc_rejections.append(per_iteration_results[iteration][device_eid]["Association Rejection"]) + connected.append( + per_iteration_results[iteration][device_eid]["Connected"] + ) + disconnected.append( + per_iteration_results[iteration][device_eid]["Disconnected"] + ) + scanning.append( + per_iteration_results[iteration][device_eid]["Scanning"] + ) + assoc_attempts.append( + per_iteration_results[iteration][device_eid]["ConnectAttempt"] + ) + assoc_rejections.append( + per_iteration_results[iteration][device_eid][ + "Association Rejection" + ] + ) connected_counts.append(connected) disconnected_counts.append(disconnected) @@ -1060,21 +1526,23 @@ def generate_overall_graph(self, per_iteration_results=None, figsize=(13, 5), _a assoc_attempt_total = assoc_attempt_total + int(count) connect_total, disconnect_total = 0, 0 - for index, _ in zip(range(len(connected_counts)), range(len(disconnected_counts))): + for index, _ in zip( + range(len(connected_counts)), range(len(disconnected_counts)) + ): for count in connected_counts[index]: connect_total = connect_total + count for count in disconnected_counts[index]: disconnect_total = disconnect_total + count assoc_rejection_total = 0 - for index in (range(len(assoc_rejection_counts))): + for index in range(len(assoc_rejection_counts)): for count in assoc_rejection_counts[index]: assoc_rejection_total = assoc_rejection_total + count - metric_totals['Disconnected'] = disconnect_total - metric_totals['Scans'] = scan_total - metric_totals['Assoc Attempts'] = assoc_attempt_total - metric_totals['Connected'] = connect_total + metric_totals["Disconnected"] = disconnect_total + metric_totals["Scans"] = scan_total + metric_totals["Assoc Attempts"] = assoc_attempt_total + metric_totals["Connected"] = connect_total metric_totals["Association Rejection"] = assoc_rejection_total # print("Final data for overall graph: ", metric_totals) @@ -1088,38 +1556,66 @@ def generate_overall_graph(self, per_iteration_results=None, figsize=(13, 5), _a if remove_border is not None: for border in remove_border: ax.spines[border].set_color(None) - if 'left' in remove_border: # to remove the y-axis labeling + if "left" in remove_border: # to remove the y-axis labeling yaxis_visible = False else: yaxis_visible = True ax.yaxis.set_visible(yaxis_visible) # creating the bar plot - colors = ('#f56122', '#00FF00', '#f5ea22', '#3D85C6', '#fa4d4d', "forestgreen") + colors = ("#f56122", "#00FF00", "#f5ea22", "#3D85C6", "#fa4d4d", "forestgreen") for bar_total, color, index in zip(bar_totals, colors, range(len(bar_labels))): plt.bar(bar_labels[index], bar_total, color=color, width=bar_width) for index, value in enumerate(bar_totals): - plt.text(index, value, "{value}".format(value=value), ha='center', rotation=bar_text_rotation, - fontsize=text_font) + plt.text( + index, + value, + "{value}".format(value=value), + ha="center", + rotation=bar_text_rotation, + fontsize=text_font, + ) - plt.xlabel("", fontweight='bold', fontsize=15) - plt.ylabel("Count", fontweight='bold', fontsize=15) + plt.xlabel("", fontweight="bold", fontsize=15) + plt.ylabel("Count", fontweight="bold", fontsize=15) - plt.xticks(color='white') + plt.xticks(color="white") plt.legend( - ['Port Resets', 'Disconnects', 'Scans', 'Assoc Attempts', "Assoc Rejections", 'Connects'], + [ + "Port Resets", + "Disconnects", + "Scans", + "Assoc Attempts", + "Assoc Rejections", + "Connects", + ], loc=_legend_loc, bbox_to_anchor=_legend_box, ncol=_legend_ncol, - fontsize=_legend_fontsize) + fontsize=_legend_fontsize, + ) plt.suptitle("Overall Graph for Port Reset Test", fontsize=16) plt.savefig("%s.png" % self.graph_image_name, dpi=96) return "%s.png" % self.graph_image_name - def per_client_graph(self, metric_totals=None, image_name=None, figsize=(13, 5), _alignment=None, remove_border=None, bar_width=0.5, - _legend_loc="best", _legend_box=None, _legend_fontsize=None, text_font=12, - bar_text_rotation=45, xaxis_name="", yaxis_name="", graph_title_size=16, - graph_title="Client %s Performance Port Reset Totals"): + def per_client_graph( + self, + metric_totals=None, + image_name=None, + figsize=(13, 5), + _alignment=None, + remove_border=None, + bar_width=0.5, + _legend_loc="best", + _legend_box=None, + _legend_fontsize=None, + text_font=12, + bar_text_rotation=45, + xaxis_name="", + yaxis_name="", + graph_title_size=16, + graph_title="Client %s Performance Port Reset Totals", + ): self.graph_image_name = image_name bar_labels = list(metric_totals.keys()) bar_totals = list(metric_totals.values()) @@ -1130,75 +1626,122 @@ def per_client_graph(self, metric_totals=None, image_name=None, figsize=(13, 5), if remove_border is not None: for border in remove_border: ax.spines[border].set_color(None) - if 'left' in remove_border: # to remove the y-axis labeling + if "left" in remove_border: # to remove the y-axis labeling yaxis_visible = False else: yaxis_visible = True ax.yaxis.set_visible(yaxis_visible) # creating the bar plot - colors = ('#f56122', '#00FF00', '#f5ea22', '#3D85C6', '#fa4d4d', "forestgreen") + colors = ("#f56122", "#00FF00", "#f5ea22", "#3D85C6", "#fa4d4d", "forestgreen") for bar_total, color, index in zip(bar_totals, colors, range(len(bar_labels))): plt.bar(bar_labels[index], bar_total, color=color, width=bar_width) for index, value in enumerate(bar_totals): - plt.text(index, value, "{value}".format(value=value), ha='center', va='bottom', rotation=bar_text_rotation, - fontsize=text_font) + plt.text( + index, + value, + "{value}".format(value=value), + ha="center", + va="bottom", + rotation=bar_text_rotation, + fontsize=text_font, + ) - plt.xlabel(xaxis_name, fontweight='bold', fontsize=15) - plt.ylabel(yaxis_name, fontweight='bold', fontsize=15) + plt.xlabel(xaxis_name, fontweight="bold", fontsize=15) + plt.ylabel(yaxis_name, fontweight="bold", fontsize=15) plt.legend( - ['Port Resets', 'Disconnects', 'Scans', 'Assoc Attempts', "Assoc Rejections", 'Connects'], + [ + "Port Resets", + "Disconnects", + "Scans", + "Assoc Attempts", + "Assoc Rejections", + "Connects", + ], loc=_legend_loc, bbox_to_anchor=_legend_box, frameon=False, - fontsize=_legend_fontsize) + fontsize=_legend_fontsize, + ) plt.suptitle(graph_title, fontsize=graph_title_size) plt.savefig("%s.png" % self.graph_image_name, dpi=96) # generate csv print(metric_totals) df = pd.DataFrame(data=metric_totals, index=[1]) print(df) - df.to_csv('{}/{}.csv'.format(self.report_path, image_name)) + df.to_csv("{}/{}.csv".format(self.report_path, image_name)) return "%s.png" % self.graph_image_name def generate_overall_graph_table(self, per_iteration_results, device_list): if self.robot_test: - self.total_resets, self.total_disconnects, self.total_scans, self.total_assoc_attempts, self.total_assoc_rejections, self.total_connects = [], [], [], [], [], [] + ( + self.total_resets, + self.total_disconnects, + self.total_scans, + self.total_assoc_attempts, + self.total_assoc_rejections, + self.total_connects, + ) = ([], [], [], [], [], []) for device_eid, _ in zip(device_list, range(len(device_list))): iteration_indexes = list(per_iteration_results.keys()) iteration_numbers = [] for iteration_index in iteration_indexes: iteration_numbers.append(int(iteration_index) + 1) - assoc_attempts, disconnected, scanning, connected, assoc_rejections, remarks = [], [], [], [], [], [] + ( + assoc_attempts, + disconnected, + scanning, + connected, + assoc_rejections, + remarks, + ) = ([], [], [], [], [], []) for iteration in per_iteration_results: - assoc_attempts.append(per_iteration_results[iteration][device_eid]["ConnectAttempt"]) - disconnected.append(per_iteration_results[iteration][device_eid]["Disconnected"]) - scanning.append(per_iteration_results[iteration][device_eid]["Scanning"]) - connected.append(per_iteration_results[iteration][device_eid]["Connected"]) - assoc_rejections.append(per_iteration_results[iteration][device_eid]["Association Rejection"]) + assoc_attempts.append( + per_iteration_results[iteration][device_eid]["ConnectAttempt"] + ) + disconnected.append( + per_iteration_results[iteration][device_eid]["Disconnected"] + ) + scanning.append( + per_iteration_results[iteration][device_eid]["Scanning"] + ) + connected.append( + per_iteration_results[iteration][device_eid]["Connected"] + ) + assoc_rejections.append( + per_iteration_results[iteration][device_eid][ + "Association Rejection" + ] + ) remarks.append(per_iteration_results[iteration][device_eid]["Remarks"]) # graph calculation - metric_labels = ['Port Resets', 'Disconnects', 'Scans', 'Association Attempts', "Association Rejections", - 'Connects'] + metric_labels = [ + "Port Resets", + "Disconnects", + "Scans", + "Association Attempts", + "Association Rejections", + "Connects", + ] metric_totals = dict.fromkeys(metric_labels) - metric_totals['Port Resets'] = self.iterations + metric_totals["Port Resets"] = self.iterations disconnect_total = 0 for count in disconnected: disconnect_total = disconnect_total + count - metric_totals['Disconnects'] = disconnect_total + metric_totals["Disconnects"] = disconnect_total scan_total = 0 for count in scanning: scan_total = scan_total + count - metric_totals['Scans'] = scan_total + metric_totals["Scans"] = scan_total assoc_attempt_total = 0 for count in assoc_attempts: assoc_attempt_total = assoc_attempt_total + count - metric_totals['Association Attempts'] = assoc_attempt_total + metric_totals["Association Attempts"] = assoc_attempt_total assoc_rejection_total = 0 for count in assoc_rejections: @@ -1208,7 +1751,7 @@ def generate_overall_graph_table(self, per_iteration_results, device_list): connect_total = 0 for count in connected: connect_total = connect_total + count - metric_totals['Connects'] = connect_total + metric_totals["Connects"] = connect_total # print(f"Final data for per client graph for {device_eid}: {metric_totals}") @@ -1228,37 +1771,65 @@ def individual_client_info(self, per_iteration_results, device_list): iteration_numbers = [] for iteration in iteration_indexes: iteration_numbers.append(int(iteration) + 1) - assoc_attempts, disconnected, scanning, connected, assoc_rejections, remarks, cx_times = [], [], [], [], [], [], [] + ( + assoc_attempts, + disconnected, + scanning, + connected, + assoc_rejections, + remarks, + cx_times, + ) = ([], [], [], [], [], [], []) for iteration in per_iteration_results: - assoc_attempts.append(per_iteration_results[iteration][device_eid]["ConnectAttempt"]) - disconnected.append(per_iteration_results[iteration][device_eid]["Disconnected"]) - scanning.append(per_iteration_results[iteration][device_eid]["Scanning"]) - connected.append(per_iteration_results[iteration][device_eid]["Connected"]) - assoc_rejections.append(per_iteration_results[iteration][device_eid]["Association Rejection"]) + assoc_attempts.append( + per_iteration_results[iteration][device_eid]["ConnectAttempt"] + ) + disconnected.append( + per_iteration_results[iteration][device_eid]["Disconnected"] + ) + scanning.append( + per_iteration_results[iteration][device_eid]["Scanning"] + ) + connected.append( + per_iteration_results[iteration][device_eid]["Connected"] + ) + assoc_rejections.append( + per_iteration_results[iteration][device_eid][ + "Association Rejection" + ] + ) remarks.append(per_iteration_results[iteration][device_eid]["Remarks"]) - cx_times.append(per_iteration_results[iteration][device_eid]["cx time (us)"]) + cx_times.append( + per_iteration_results[iteration][device_eid]["cx time (us)"] + ) # graph calculation - metric_labels = ['Port Resets', 'Disconnects', 'Scans', 'Association Attempts', "Association Rejections", - 'Connects'] + metric_labels = [ + "Port Resets", + "Disconnects", + "Scans", + "Association Attempts", + "Association Rejections", + "Connects", + ] metric_totals = dict.fromkeys(metric_labels) - metric_totals['Port Resets'] = self.iterations + metric_totals["Port Resets"] = self.iterations disconnect_total = 0 for count in disconnected: disconnect_total = disconnect_total + count - metric_totals['Disconnects'] = disconnect_total + metric_totals["Disconnects"] = disconnect_total scan_total = 0 for count in scanning: scan_total = scan_total + count - metric_totals['Scans'] = scan_total + metric_totals["Scans"] = scan_total assoc_attempt_total = 0 for count in assoc_attempts: assoc_attempt_total = assoc_attempt_total + count - metric_totals['Association Attempts'] = assoc_attempt_total + metric_totals["Association Attempts"] = assoc_attempt_total assoc_rejection_total = 0 for count in assoc_rejections: @@ -1268,30 +1839,51 @@ def individual_client_info(self, per_iteration_results, device_list): connect_total = 0 for count in connected: connect_total = connect_total + count - metric_totals['Connects'] = connect_total + metric_totals["Connects"] = connect_total # print(f"Final data for per client graph for {device_eid}: {metric_totals}") if "1.1." in device_eid: # setting the title for per client graph and table represent title. - android_user_name = self.interop.get_device_details(device=device_eid, query="user-name") + android_user_name = self.interop.get_device_details( + device=device_eid, query="user-name" + ) self.lf_report.set_obj_html( - "Port Resets for Client " + str(android_user_name) + " (" + str(device_eid.split(".")[2]) + ")", - "The below table & graph displays details of " + str(android_user_name) + " device.") + "Port Resets for Client " + + str(android_user_name) + + " (" + + str(device_eid.split(".")[2]) + + ")", + "The below table & graph displays details of " + + str(android_user_name) + + " device.", + ) self.lf_report.build_objective() else: # setting the title for per client graph and table represent title. self.lf_report.set_obj_html( "Port Resets for Client " + str(device_eid) + ".", - "The below table & graph displays details of " + str(device_eid) + " device.") + "The below table & graph displays details of " + + str(device_eid) + + " device.", + ) self.lf_report.build_objective() # per client graph generation - client_graph = self.per_client_graph(metric_totals=metric_totals, image_name="per_client_" + str(device_index), figsize=(13, 5), - _alignment={"left": 0.1}, remove_border=['top', 'right'], - _legend_loc="upper left", _legend_fontsize=9, _legend_box=(1, 1), - yaxis_name="COUNT", - graph_title="Client " + str(device_eid) + " Total Reset Performance Graph") + client_graph = self.per_client_graph( + metric_totals=metric_totals, + image_name="per_client_" + str(device_index), + figsize=(13, 5), + _alignment={"left": 0.1}, + remove_border=["top", "right"], + _legend_loc="upper left", + _legend_fontsize=9, + _legend_box=(1, 1), + yaxis_name="COUNT", + graph_title="Client " + + str(device_eid) + + " Total Reset Performance Graph", + ) # graph1 = self.generate_per_station_graph() self.lf_report.set_graph_image(client_graph) self.lf_report.move_graph_image() @@ -1306,12 +1898,12 @@ def individual_client_info(self, per_iteration_results, device_list): "Association Rejection": assoc_rejections, "Connected": connected, "Connection Time (us)": cx_times, - "Remarks": remarks + "Remarks": remarks, } client_table_df = pd.DataFrame(per_iteration_table) self.lf_report.set_table_dataframe(client_table_df) self.lf_report.build_table() - self.lf_report.save_csv('overall_report.csv', client_table_df) + self.lf_report.save_csv("overall_report.csv", client_table_df) def generate_report(self, per_iteration_results=None, test_duration=None): try: @@ -1344,37 +1936,49 @@ def generate_report(self, per_iteration_results=None, test_duration=None): self.lf_report.set_date(date) self.lf_report.build_banner_cover() - self.lf_report.set_obj_html("Objective", - "The Port Reset Test simulates a scenario where multiple WiFi stations are created " - "and connected to the Access Point (AP) under test. These stations are then randomly " - "disconnected and reconnected at varying intervals, mimicking a busy enterprise or " - "large public venue environment with frequent station arrivals and departures. " - "The primary objective of this test is to thoroughly assess the core Access Point " - "functions' control and management aspects under stress.

" - ) + self.lf_report.set_obj_html( + "Objective", + "The Port Reset Test simulates a scenario where multiple WiFi stations are created " + "and connected to the Access Point (AP) under test. These stations are then randomly " + "disconnected and reconnected at varying intervals, mimicking a busy enterprise or " + "large public venue environment with frequent station arrivals and departures. " + "The primary objective of this test is to thoroughly assess the core Access Point " + "functions' control and management aspects under stress.

", + ) self.lf_report.build_objective() self.lf_report.set_table_title("Test Setup Information") self.lf_report.build_table_title() - self.lf_report.test_setup_table(value="Basic Test Information", test_setup_data=test_setup_info) - - self.lf_report.set_obj_html("Overall Port Resets Graph", - "The following graph presents an overview of different events during the test, " - "including Port Resets, Disconnects, Scans, Association Attempts, Association Rejections and Connections. " - "Each category represents the total count achieved by all clients.

" - "1. Port Resets: Total number of reset occurrences provided as test input.
" - "2. Disconnects: Total number of disconnects that happened for all clients during the test when WiFi was disabled.
" - "3. Scans: Total number of scanning states achieved by all clients during the test when the network is re-enabled.
" - "4. Association Attempts: Total number of association attempts (Associating state) made by all clients after WiFi is re-enabled in the full test.
" - "4. Association Rejections: Total number of association rejections made by all clients after WiFi is re-enabled in the full test.
" - "6. Connected: Total number of successful connections (Associated state) achieved by all clients during the test when WiFi is re-enabled.
" - # " Here real clients used is "+ str(self.clients) + "and number of resets provided is " + str(self.iterations) - ) + self.lf_report.test_setup_table( + value="Basic Test Information", test_setup_data=test_setup_info + ) + + self.lf_report.set_obj_html( + "Overall Port Resets Graph", + "The following graph presents an overview of different events during the test, " + "including Port Resets, Disconnects, Scans, Association Attempts, Association Rejections and Connections. " + "Each category represents the total count achieved by all clients.

" + "1. Port Resets: Total number of reset occurrences provided as test input.
" + "2. Disconnects: Total number of disconnects that happened for all clients during the test when WiFi was disabled.
" + "3. Scans: Total number of scanning states achieved by all clients during the test when the network is re-enabled.
" + "4. Association Attempts: Total number of association attempts (Associating state) made by all clients after WiFi is re-enabled in the full test.
" + "4. Association Rejections: Total number of association rejections made by all clients after WiFi is re-enabled in the full test.
" + "6. Connected: Total number of successful connections (Associated state) achieved by all clients during the test when WiFi is re-enabled.
", + # " Here real clients used is "+ str(self.clients) + "and number of resets provided is " + str(self.iterations) + ) self.lf_report.build_objective() - overall_graph = self.generate_overall_graph(per_iteration_results=per_iteration_results, figsize=(13, 5), _alignment=None, bar_width=0.5, - _legend_loc="upper center", _legend_ncol=6, _legend_fontsize=10, - _legend_box=(0.5, -0.06), text_font=12) + overall_graph = self.generate_overall_graph( + per_iteration_results=per_iteration_results, + figsize=(13, 5), + _alignment=None, + bar_width=0.5, + _legend_loc="upper center", + _legend_ncol=6, + _legend_fontsize=10, + _legend_box=(0.5, -0.06), + text_font=12, + ) # graph1 = self.generate_per_station_graph() self.lf_report.set_graph_image(overall_graph) self.lf_report.move_graph_image() @@ -1382,17 +1986,41 @@ def generate_report(self, per_iteration_results=None, test_duration=None): all_devices = self.adb_device_list + self.all_laptops - self.generate_overall_graph_table(per_iteration_results=per_iteration_results, device_list=all_devices) + self.generate_overall_graph_table( + per_iteration_results=per_iteration_results, device_list=all_devices + ) - device_names, device_types, model, user_names, release = [], [], [], [], [] # noqa: F841 + device_names, device_types, model, user_names, release = ( # noqa: F841 + [], + [], + [], + [], + [], + ) for device_eid in self.adb_device_list: - device_names.append(self.interop.get_device_details(device=device_eid, query="name")) - device_types.append(self.interop.get_device_details(device=device_eid, query="device-type")) - user_names.append(self.interop.get_device_details(device=device_eid, query="user-name")) + device_names.append( + self.interop.get_device_details(device=device_eid, query="name") + ) + device_types.append( + self.interop.get_device_details( + device=device_eid, query="device-type" + ) + ) + user_names.append( + self.interop.get_device_details( + device=device_eid, query="user-name" + ) + ) for device_eid in self.all_laptops: device_names.append(device_eid) - user_names.append(self.interop.get_laptop_devices_details(device=device_eid, query="host_name")) - hw_version = self.interop.get_laptop_devices_details(device=device_eid, query="hw_version") + user_names.append( + self.interop.get_laptop_devices_details( + device=device_eid, query="host_name" + ) + ) + hw_version = self.interop.get_laptop_devices_details( + device=device_eid, query="hw_version" + ) if "Linux" in hw_version: device_type = "Linux" elif "Win" in hw_version: @@ -1418,12 +2046,14 @@ def generate_report(self, per_iteration_results=None, test_duration=None): "Scans": self.total_scans, "Assoc Attemts": self.total_assoc_attempts, "Assoc Rejects": self.total_assoc_rejections, - "Connects": self.total_connects + "Connects": self.total_connects, } device_summary_df = pd.DataFrame(device_summary_table) self.lf_report.set_table_dataframe(device_summary_df) self.lf_report.build_table() - self.individual_client_info(per_iteration_results=per_iteration_results, device_list=all_devices) + self.individual_client_info( + per_iteration_results=per_iteration_results, device_list=all_devices + ) # self.lf_report.set_obj_html("Tested Clients Information:", # "The table displays details of real clients which are involved in the test.") # self.lf_report.build_objective() @@ -1431,9 +2061,11 @@ def generate_report(self, per_iteration_results=None, test_duration=None): self.lf_report.build_footer() self.lf_report.write_html() if self.dowebgui: - self.lf_report.write_pdf(_page_size='A4', _orientation='Portrait') + self.lf_report.write_pdf(_page_size="A4", _orientation="Portrait") else: - self.lf_report.write_pdf_with_timestamp(_page_size='A4', _orientation='Portrait') + self.lf_report.write_pdf_with_timestamp( + _page_size="A4", _orientation="Portrait" + ) # self.lf_report.move_data(directory="log", _file_name="port_reset.log") except Exception as e: @@ -1447,7 +2079,11 @@ def add_live_view_images_to_report(self): it's added to the `report` on a new page; otherwise, it's skipped. """ for floor in range(0, int(self.total_floors)): - port_reset_image_path = os.path.join(self.result_dir, "live_view_images", f"port_reset_{self.test_name}_{floor + 1}.png") + port_reset_image_path = os.path.join( + self.result_dir, + "live_view_images", + f"port_reset_{self.test_name}_{floor + 1}.png", + ) timeout_sec = 60 start_time = time.time() @@ -1457,9 +2093,13 @@ def add_live_view_images_to_report(self): break time.sleep(1) if os.path.exists(port_reset_image_path): - self.lf_report.set_custom_html('
') + self.lf_report.set_custom_html( + '
' + ) self.lf_report.build_custom() - self.lf_report.set_custom_html(f'') + self.lf_report.set_custom_html( + f'' + ) self.lf_report.build_custom() def generate_report_for_robo(self): @@ -1491,36 +2131,40 @@ def generate_report_for_robo(self): self.lf_report.set_date(date) self.lf_report.build_banner_cover() - self.lf_report.set_obj_html("Objective", - "The Port Reset Test simulates a scenario where multiple WiFi stations are created " - "and connected to the Access Point (AP) under test. These stations are then randomly " - "disconnected and reconnected at varying intervals, mimicking a busy enterprise or " - "large public venue environment with frequent station arrivals and departures. " - "The primary objective of this test is to thoroughly assess the core Access Point " - "functions' control and management aspects under stress.

" - ) + self.lf_report.set_obj_html( + "Objective", + "The Port Reset Test simulates a scenario where multiple WiFi stations are created " + "and connected to the Access Point (AP) under test. These stations are then randomly " + "disconnected and reconnected at varying intervals, mimicking a busy enterprise or " + "large public venue environment with frequent station arrivals and departures. " + "The primary objective of this test is to thoroughly assess the core Access Point " + "functions' control and management aspects under stress.

", + ) self.lf_report.build_objective() self.lf_report.set_table_title("Test Setup Information") self.lf_report.build_table_title() - self.lf_report.test_setup_table(value="Basic Test Information", test_setup_data=test_setup_info) + self.lf_report.test_setup_table( + value="Basic Test Information", test_setup_data=test_setup_info + ) - if (self.dowebgui and self.get_live_view): + if self.dowebgui and self.get_live_view: self.lf_report.set_custom_html("

Overall Port reset's Heatmap:

") self.lf_report.build_custom() self.add_live_view_images_to_report() - self.lf_report.set_obj_html("Overall Port Resets Graphs", - "The following graph presents an overview of different events during the test, " - "including Port Resets, Disconnects, Scans, Association Attempts, Association Rejections and Connections. " - "Each category represents the total count achieved by all clients.

" - "1. Port Resets: Total number of reset occurrences provided as test input.
" - "2. Disconnects: Total number of disconnects that happened for all clients during the test when WiFi was disabled.
" - "3. Scans: Total number of scanning states achieved by all clients during the test when the network is re-enabled.
" - "4. Association Attempts: Total number of association attempts (Associating state) made by all clients after WiFi is re-enabled in the full test.
" - "4. Association Rejections: Total number of association rejections made by all clients after WiFi is re-enabled in the full test.
" - "6. Connected: Total number of successful connections (Associated state) achieved by all clients during the test when WiFi is re-enabled.
" - # " Here real clients used is "+ str(self.clients) + "and number of resets provided is " + str(self.iterations) - ) + self.lf_report.set_obj_html( + "Overall Port Resets Graphs", + "The following graph presents an overview of different events during the test, " + "including Port Resets, Disconnects, Scans, Association Attempts, Association Rejections and Connections. " + "Each category represents the total count achieved by all clients.

" + "1. Port Resets: Total number of reset occurrences provided as test input.
" + "2. Disconnects: Total number of disconnects that happened for all clients during the test when WiFi was disabled.
" + "3. Scans: Total number of scanning states achieved by all clients during the test when the network is re-enabled.
" + "4. Association Attempts: Total number of association attempts (Associating state) made by all clients after WiFi is re-enabled in the full test.
" + "4. Association Rejections: Total number of association rejections made by all clients after WiFi is re-enabled in the full test.
" + "6. Connected: Total number of successful connections (Associated state) achieved by all clients during the test when WiFi is re-enabled.
", + # " Here real clients used is "+ str(self.clients) + "and number of resets provided is " + str(self.iterations) + ) self.lf_report.build_objective() for coordinate_index in range(len(self.coordinate_list)): if self.rotation_enabled: @@ -1529,38 +2173,79 @@ def generate_report_for_robo(self): angle = self.rotation_list[angle_index] if ( - coordinate not in self.port_reset_data or - angle not in self.port_reset_data[coordinate] or - 'per_iteration_results' not in self.port_reset_data[coordinate][angle] + coordinate not in self.port_reset_data + or angle not in self.port_reset_data[coordinate] + or "per_iteration_results" + not in self.port_reset_data[coordinate][angle] ): continue - per_iteration_results = self.port_reset_data[coordinate][angle]['per_iteration_results'] - self.lf_report.set_obj_html(_obj_title=f"Overall Port reset stats at Coordinate: {self.coordinate_list[coordinate_index]} | Rotation Angle: {self.rotation_list[angle_index]}°", - _obj="") + per_iteration_results = self.port_reset_data[coordinate][angle][ + "per_iteration_results" + ] + self.lf_report.set_obj_html( + _obj_title=f"Overall Port reset stats at Coordinate: {self.coordinate_list[coordinate_index]} | Rotation Angle: {self.rotation_list[angle_index]}°", + _obj="", + ) self.lf_report.build_objective() graph_suffix = f"{self.coordinate_list[coordinate_index]}_{self.rotation_list[angle_index]}" - overall_graph = self.generate_overall_graph(per_iteration_results=per_iteration_results, figsize=(13, 5), _alignment=None, bar_width=0.5, - _legend_loc="upper center", _legend_ncol=6, _legend_fontsize=10, - _legend_box=(0.5, -0.06), text_font=12, graph_suffix=graph_suffix) + overall_graph = self.generate_overall_graph( + per_iteration_results=per_iteration_results, + figsize=(13, 5), + _alignment=None, + bar_width=0.5, + _legend_loc="upper center", + _legend_ncol=6, + _legend_fontsize=10, + _legend_box=(0.5, -0.06), + text_font=12, + graph_suffix=graph_suffix, + ) # graph1 = self.generate_per_station_graph() self.lf_report.set_graph_image(overall_graph) self.lf_report.move_graph_image() self.lf_report.build_graph() all_devices = self.adb_device_list + self.all_laptops - self.generate_overall_graph_table(per_iteration_results=per_iteration_results, device_list=all_devices) + self.generate_overall_graph_table( + per_iteration_results=per_iteration_results, + device_list=all_devices, + ) - device_names, device_types, model, user_names, release = [], [], [], [], [] # noqa: F841 + device_names, device_types, model, user_names, release = ( + [], + [], + [], + [], + [], + ) for device_eid in self.adb_device_list: - device_names.append(self.interop.get_device_details(device=device_eid, query="name")) - device_types.append(self.interop.get_device_details(device=device_eid, query="device-type")) - user_names.append(self.interop.get_device_details(device=device_eid, query="user-name")) + device_names.append( + self.interop.get_device_details( + device=device_eid, query="name" + ) + ) + device_types.append( + self.interop.get_device_details( + device=device_eid, query="device-type" + ) + ) + user_names.append( + self.interop.get_device_details( + device=device_eid, query="user-name" + ) + ) for device_eid in self.all_laptops: device_names.append(device_eid) - user_names.append(self.interop.get_laptop_devices_details(device=device_eid, query="host_name")) - hw_version = self.interop.get_laptop_devices_details(device=device_eid, query="hw_version") + user_names.append( + self.interop.get_laptop_devices_details( + device=device_eid, query="host_name" + ) + ) + hw_version = self.interop.get_laptop_devices_details( + device=device_eid, query="hw_version" + ) if "Linux" in hw_version: device_type = "Linux" elif "Win" in hw_version: @@ -1586,7 +2271,7 @@ def generate_report_for_robo(self): "Scans": self.total_scans, "Assoc Attemts": self.total_assoc_attempts, "Assoc Rejects": self.total_assoc_rejections, - "Connects": self.total_connects + "Connects": self.total_connects, } device_summary_df = pd.DataFrame(device_summary_table) self.lf_report.set_table_dataframe(device_summary_df) @@ -1595,36 +2280,73 @@ def generate_report_for_robo(self): coordinate = self.coordinate_list[coordinate_index] if ( - coordinate not in self.port_reset_data or - 'per_iteration_results' not in self.port_reset_data[coordinate] + coordinate not in self.port_reset_data + or "per_iteration_results" not in self.port_reset_data[coordinate] ): continue - per_iteration_results = self.port_reset_data[coordinate]['per_iteration_results'] - self.lf_report.set_obj_html(_obj_title=f"Overall Port reset stats at Coordinate: {self.coordinate_list[coordinate_index]}", - _obj="") + per_iteration_results = self.port_reset_data[coordinate][ + "per_iteration_results" + ] + self.lf_report.set_obj_html( + _obj_title=f"Overall Port reset stats at Coordinate: {self.coordinate_list[coordinate_index]}", + _obj="", + ) self.lf_report.build_objective() graph_suffix = f"{self.coordinate_list[coordinate_index]}" - overall_graph = self.generate_overall_graph(per_iteration_results=per_iteration_results, figsize=(13, 5), _alignment=None, bar_width=0.5, - _legend_loc="upper center", _legend_ncol=6, _legend_fontsize=10, - _legend_box=(0.5, -0.06), text_font=12, graph_suffix=graph_suffix) + overall_graph = self.generate_overall_graph( + per_iteration_results=per_iteration_results, + figsize=(13, 5), + _alignment=None, + bar_width=0.5, + _legend_loc="upper center", + _legend_ncol=6, + _legend_fontsize=10, + _legend_box=(0.5, -0.06), + text_font=12, + graph_suffix=graph_suffix, + ) # graph1 = self.generate_per_station_graph() self.lf_report.set_graph_image(overall_graph) self.lf_report.move_graph_image() self.lf_report.build_graph() all_devices = self.adb_device_list + self.all_laptops - self.generate_overall_graph_table(per_iteration_results=per_iteration_results, device_list=all_devices) + self.generate_overall_graph_table( + per_iteration_results=per_iteration_results, device_list=all_devices + ) - device_names, device_types, model, user_names, release = [], [], [], [], [] # noqa: F841 + device_names, device_types, model, user_names, release = ( # noqa: F841 + [], + [], + [], + [], + [], + ) for device_eid in self.adb_device_list: - device_names.append(self.interop.get_device_details(device=device_eid, query="name")) - device_types.append(self.interop.get_device_details(device=device_eid, query="device-type")) - user_names.append(self.interop.get_device_details(device=device_eid, query="user-name")) + device_names.append( + self.interop.get_device_details(device=device_eid, query="name") + ) + device_types.append( + self.interop.get_device_details( + device=device_eid, query="device-type" + ) + ) + user_names.append( + self.interop.get_device_details( + device=device_eid, query="user-name" + ) + ) for device_eid in self.all_laptops: device_names.append(device_eid) - user_names.append(self.interop.get_laptop_devices_details(device=device_eid, query="host_name")) - hw_version = self.interop.get_laptop_devices_details(device=device_eid, query="hw_version") + user_names.append( + self.interop.get_laptop_devices_details( + device=device_eid, query="host_name" + ) + ) + hw_version = self.interop.get_laptop_devices_details( + device=device_eid, query="hw_version" + ) if "Linux" in hw_version: device_type = "Linux" elif "Win" in hw_version: @@ -1650,7 +2372,7 @@ def generate_report_for_robo(self): "Scans": self.total_scans, "Assoc Attemts": self.total_assoc_attempts, "Assoc Rejects": self.total_assoc_rejections, - "Connects": self.total_connects + "Connects": self.total_connects, } device_summary_df = pd.DataFrame(device_summary_table) self.lf_report.set_table_dataframe(device_summary_df) @@ -1658,9 +2380,11 @@ def generate_report_for_robo(self): self.lf_report.build_footer() self.lf_report.write_html() if self.dowebgui: - self.lf_report.write_pdf(_page_size='A4', _orientation='Portrait') + self.lf_report.write_pdf(_page_size="A4", _orientation="Portrait") else: - self.lf_report.write_pdf_with_timestamp(_page_size='A4', _orientation='Portrait') + self.lf_report.write_pdf_with_timestamp( + _page_size="A4", _orientation="Portrait" + ) def write_overall_csv(self, per_iteration_results): """ @@ -1674,26 +2398,38 @@ def write_overall_csv(self, per_iteration_results): for device_eid, metrics in iteration_metrics.items(): if device_eid not in totals_per_device: totals_per_device[device_eid] = { - 'ConnectAttempt': 0, - 'Disconnected': 0, - 'Scanning': 0, - 'Association Rejection': 0, - 'Connected': 0, - 'Iterations': 0, - 'Status': 'running' + "ConnectAttempt": 0, + "Disconnected": 0, + "Scanning": 0, + "Association Rejection": 0, + "Connected": 0, + "Iterations": 0, + "Status": "running", } # Use safe addition (handles None and missing keys) - totals_per_device[device_eid]['ConnectAttempt'] += metrics.get('ConnectAttempt', 0) or 0 - totals_per_device[device_eid]['Disconnected'] += metrics.get('Disconnected', 0) or 0 - totals_per_device[device_eid]['Scanning'] += metrics.get('Scanning', 0) or 0 - totals_per_device[device_eid]['Association Rejection'] += metrics.get('Association Rejection', 0) or 0 - totals_per_device[device_eid]['Connected'] += metrics.get('Connected', 0) or 0 - totals_per_device[device_eid]['Iterations'] += 1 + totals_per_device[device_eid]["ConnectAttempt"] += ( + metrics.get("ConnectAttempt", 0) or 0 + ) + totals_per_device[device_eid]["Disconnected"] += ( + metrics.get("Disconnected", 0) or 0 + ) + totals_per_device[device_eid]["Scanning"] += ( + metrics.get("Scanning", 0) or 0 + ) + totals_per_device[device_eid]["Association Rejection"] += ( + metrics.get("Association Rejection", 0) or 0 + ) + totals_per_device[device_eid]["Connected"] += ( + metrics.get("Connected", 0) or 0 + ) + totals_per_device[device_eid]["Iterations"] += 1 # Create DataFrame - summary_df = pd.DataFrame.from_dict(totals_per_device, orient='index').reset_index() - summary_df = summary_df.rename(columns={'index': 'Client'}) + summary_df = pd.DataFrame.from_dict( + totals_per_device, orient="index" + ).reset_index() + summary_df = summary_df.rename(columns={"index": "Client"}) self.result_df = summary_df.copy() # Save and print summary_df.to_csv(f"{self.report_path}/overall_reset.csv", index=False) @@ -1703,7 +2439,7 @@ def write_overall_csv(self, per_iteration_results): def main(): - help_summary = '''\ + help_summary = """\ The LANforge interop port reset test enables users to use real Wi-Fi stations and connect them to the Access Point being tested. It then disconnects and reconnects a given number of stations at different time intervals. This test helps evaluate how well the AP handles a dynamic and busy network environment with devices joining and @@ -1711,12 +2447,12 @@ def main(): The test will basically disconnect & reconnect to the same network with real devices such as android, linux, windows and generate a report. - ''' + """ parser = argparse.ArgumentParser( prog=__file__, formatter_class=argparse.RawTextHelpFormatter, allow_abbrev=False, - description=''' + description=""" NAME: lf_interop_port_reset_test.py PURPOSE: @@ -1763,69 +2499,158 @@ def main(): Copyright (C) 2020-2026 Candela Technologies Inc INCLUDE_IN_README: False -''') - - parser.add_argument("--lanforge_ip", default='192.168.1.31', - help='Specify the LANforge GUI to connect to, assumes port 8080') - - parser.add_argument("--lanforge_port", default='8080', help='Specify the LANforge manager HTTP port') - - parser.add_argument("--upstream_port", default='192.168.1.31', - help='Specify the upstream port feeding the DUT, either as a port name ' - '(e.g. eth1) or as its IP') - - parser.add_argument("--dut", default="TestDut", - help='Specify DUT name on which the test will be running.') - - parser.add_argument("--ssid", default="Netgear2g", - help='Specify ssid on which the test will be running.') - - parser.add_argument("--passwd", default="Password@123", - help='Specify encryption password on which the test will be running.') - - parser.add_argument("--encryp", default="psk2", - help='Specify the encryption type on which the test will be running eg :open|psk|psk2|sae|psk2jsae') - - parser.add_argument("--iterations", type=int, default=2, - help='Specify how many reset iterations to run. eg: 2') - - parser.add_argument("--reset_interval", type=int, default=5, - help='Specify the time interval in seconds to wait between reset iterations.') - - parser.add_argument('--device_list', help='Enter the devices on which the test should be run', default=None) - - parser.add_argument('--no_forget_networks', - help='Currently enterprise authentication does not support forget all networks.' - 'So, mention this argument when enterprise securities are selected.', default=None, - action="store_true") +""", + ) + + parser.add_argument( + "--lanforge_ip", + default="192.168.1.31", + help="Specify the LANforge GUI to connect to, assumes port 8080", + ) + + parser.add_argument( + "--lanforge_port", default="8080", help="Specify the LANforge manager HTTP port" + ) + + parser.add_argument( + "--upstream_port", + default="192.168.1.31", + help="Specify the upstream port feeding the DUT, either as a port name " + "(e.g. eth1) or as its IP", + ) + + parser.add_argument( + "--dut", + default="TestDut", + help="Specify DUT name on which the test will be running.", + ) + + parser.add_argument( + "--ssid", + default="Netgear2g", + help="Specify ssid on which the test will be running.", + ) + + parser.add_argument( + "--passwd", + default="Password@123", + help="Specify encryption password on which the test will be running.", + ) + + parser.add_argument( + "--encryp", + default="psk2", + help="Specify the encryption type on which the test will be running eg :open|psk|psk2|sae|psk2jsae", + ) + + parser.add_argument( + "--iterations", + type=int, + default=2, + help="Specify how many reset iterations to run. eg: 2", + ) + + parser.add_argument( + "--reset_interval", + type=int, + default=5, + help="Specify the time interval in seconds to wait between reset iterations.", + ) + + parser.add_argument( + "--device_list", + help="Enter the devices on which the test should be run", + default=None, + ) + + parser.add_argument( + "--no_forget_networks", + help="Currently enterprise authentication does not support forget all networks." + "So, mention this argument when enterprise securities are selected.", + default=None, + action="store_true", + ) # parser.add_argument("--wait_time", type=int, default=20, # help='Specify the wait time in seconds for WIFI Supplicant Logs.') - parser.add_argument("--android_releases", nargs='*', default=["12"], - help='Specify which Android releases (SDK versions) may take part in the test; android ' - 'devices on any other release are skipped. Laptops are unaffected. ' - 'eg:- --android_releases 11 12 13') + parser.add_argument( + "--android_releases", + nargs="*", + default=["12"], + help="Specify which Android releases (SDK versions) may take part in the test; android " + "devices on any other release are skipped. Laptops are unaffected. " + "eg:- --android_releases 11 12 13", + ) # logging configuration: - parser.add_argument('--log_level', default=None, - help='Set logging level: debug | info | warning | error | critical') - - parser.add_argument("--lf_logger_config_json", - help="--lf_logger_config_json , json configuration of logger") - - parser.add_argument('--help_summary', help='Show summary of what this script does', default=None, - action="store_true") - - parser.add_argument('--dowebgui', help="If true will execute script for webgui", action='store_true') - - parser.add_argument('--result_dir', help='Specify the result dir to store the runtime logs', default='') - parser.add_argument('--test_name', help='Specify test name to store the runtime csv results', default=None) - parser.add_argument("--robot_test", help='to trigger robot test', action='store_true') - parser.add_argument('--robot_ip', type=str, default='localhost', help='hostname for where Robot server is running') - parser.add_argument('--robot_port', type=str, default=5000, help='port Robot HTTP service is running on') - parser.add_argument('--coordinate', type=str, default='', help="The coordinate contains list of coordinates to be ") - parser.add_argument('--rotation', type=str, default='', help="The set of angles to rotate at a particular point") - parser.add_argument('--get_live_view', help="If true will heatmap will be generated from testhouse automation WebGui ", action='store_true') - parser.add_argument('--total_floors', help="Total floors from testhouse automation WebGui ", default="0") + parser.add_argument( + "--log_level", + default=None, + help="Set logging level: debug | info | warning | error | critical", + ) + + parser.add_argument( + "--lf_logger_config_json", + help="--lf_logger_config_json , json configuration of logger", + ) + + parser.add_argument( + "--help_summary", + help="Show summary of what this script does", + default=None, + action="store_true", + ) + + parser.add_argument( + "--dowebgui", help="If true will execute script for webgui", action="store_true" + ) + + parser.add_argument( + "--result_dir", + help="Specify the result dir to store the runtime logs", + default="", + ) + parser.add_argument( + "--test_name", + help="Specify test name to store the runtime csv results", + default=None, + ) + parser.add_argument( + "--robot_test", help="to trigger robot test", action="store_true" + ) + parser.add_argument( + "--robot_ip", + type=str, + default="localhost", + help="hostname for where Robot server is running", + ) + parser.add_argument( + "--robot_port", + type=str, + default=5000, + help="port Robot HTTP service is running on", + ) + parser.add_argument( + "--coordinate", + type=str, + default="", + help="The coordinate contains list of coordinates to be ", + ) + parser.add_argument( + "--rotation", + type=str, + default="", + help="The set of angles to rotate at a particular point", + ) + parser.add_argument( + "--get_live_view", + help="If true will heatmap will be generated from testhouse automation WebGui ", + action="store_true", + ) + parser.add_argument( + "--total_floors", + help="Total floors from testhouse automation WebGui ", + default="0", + ) args = parser.parse_args() # help summary @@ -1843,32 +2668,35 @@ def main(): logger_config.lf_logger_config_json = args.lf_logger_config_json logger_config.load_lf_logger_config() - port_reset_test = InteropPortReset(lanforge_ip=args.lanforge_ip, - lanforge_port=args.lanforge_port, - dut=args.dut, - ssid=args.ssid, - passwd=args.passwd, - encryption=args.encryp, - iterations=args.iterations, - # clients=args.clients, - reset_interval_sec=args.reset_interval, - android_releases=args.android_releases, - upstream_port=args.upstream_port, - device_list=args.device_list, - forget_network=not args.no_forget_networks, - dowebgui=args.dowebgui, - result_dir=args.result_dir, - test_name=args.test_name, - robot_test=args.robot_test, - robot_ip=args.robot_ip, - robot_port=args.robot_port, - coordinate=args.coordinate, - rotation=args.rotation, - get_live_view=args.get_live_view, - total_floors=args.total_floors - ) - - port_reset_test.upstream_port = port_reset_test.change_port_to_ip(port_reset_test.upstream_port) + port_reset_test = InteropPortReset( + lanforge_ip=args.lanforge_ip, + lanforge_port=args.lanforge_port, + dut=args.dut, + ssid=args.ssid, + passwd=args.passwd, + encryption=args.encryp, + iterations=args.iterations, + # clients=args.clients, + reset_interval_sec=args.reset_interval, + android_releases=args.android_releases, + upstream_port=args.upstream_port, + device_list=args.device_list, + forget_network=not args.no_forget_networks, + dowebgui=args.dowebgui, + result_dir=args.result_dir, + test_name=args.test_name, + robot_test=args.robot_test, + robot_ip=args.robot_ip, + robot_port=args.robot_port, + coordinate=args.coordinate, + rotation=args.rotation, + get_live_view=args.get_live_view, + total_floors=args.total_floors, + ) + + port_reset_test.upstream_port = port_reset_test.change_port_to_ip( + port_reset_test.upstream_port + ) port_reset_test.base_interop_profile.server_ip = port_reset_test.upstream_port print(port_reset_test.upstream_port) @@ -1878,18 +2706,30 @@ def main(): else: per_iteration_results, test_duration = port_reset_test.run() if args.dowebgui: - port_reset_test.result_df['Status'] = 'stopped' + port_reset_test.result_df["Status"] = "stopped" if port_reset_test.robot_test: - port_reset_test.result_df.to_csv(f"{port_reset_test.report_path}/overall_reset_{port_reset_test.current_coordinate}.csv", index=False) - port_reset_test.result_df.to_csv(f"{port_reset_test.result_dir}/overall_reset_{port_reset_test.current_coordinate}.csv", index=False) + port_reset_test.result_df.to_csv( + f"{port_reset_test.report_path}/overall_reset_{port_reset_test.current_coordinate}.csv", + index=False, + ) + port_reset_test.result_df.to_csv( + f"{port_reset_test.result_dir}/overall_reset_{port_reset_test.current_coordinate}.csv", + index=False, + ) else: - port_reset_test.result_df.to_csv(f"{port_reset_test.report_path}/overall_reset.csv", index=False) - port_reset_test.result_df.to_csv(f"{port_reset_test.result_dir}/overall_reset.csv", index=False) + port_reset_test.result_df.to_csv( + f"{port_reset_test.report_path}/overall_reset.csv", index=False + ) + port_reset_test.result_df.to_csv( + f"{port_reset_test.result_dir}/overall_reset.csv", index=False + ) if port_reset_test.robot_test: port_reset_test.generate_report_for_robo() else: - port_reset_test.generate_report(per_iteration_results=per_iteration_results, test_duration=test_duration) + port_reset_test.generate_report( + per_iteration_results=per_iteration_results, test_duration=test_duration + ) -if __name__ == '__main__': +if __name__ == "__main__": main() From 15428c0dbd98de96075e45a638d8f0955d0ce9c0 Mon Sep 17 00:00:00 2001 From: Narayana-CT Date: Sat, 22 Aug 2026 14:36:37 +0530 Subject: [PATCH 09/13] lf_interop_port_reset_test.py: add tokenize_wifi_msg() for wifi-msg matching Signed-off-by: Narayana-CT --- py-scripts/lf_interop_port_reset_test.py | 28 +++++++++++++++++++----- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/py-scripts/lf_interop_port_reset_test.py b/py-scripts/lf_interop_port_reset_test.py index 9bc298d97..de76e8b6c 100755 --- a/py-scripts/lf_interop_port_reset_test.py +++ b/py-scripts/lf_interop_port_reset_test.py @@ -49,6 +49,7 @@ """ import json +import re import sys import os import importlib @@ -332,6 +333,17 @@ def get_last_wifi_msg_timestamp(self): logging.info(f"Last WiFi Message Time Stamp: {last_timestamp}") return last_timestamp + def tokenize_wifi_msg(self, text): + """Take a wifi message string and return its tokens as a list of strings. + + "en0: STA is connected." -> ["en0", "STA", "is", "connected"]""" + tokens = [] + for token in re.split(r"[\s:]+", text.strip()): + token = token.strip(".,;") + if token: + tokens.append(token) + return tokens + def count_wifi_msg_matches( self, wifi_messages=None, message_keys=None, device_eid=None, match_text=None ): @@ -343,7 +355,9 @@ def count_wifi_msg_matches( wifi_msg_text = wifi_messages[index][message_key]["text"] message_resource = wifi_messages[index][message_key]["resource"] if type(wifi_msg_text) is str: - message_tokens = wifi_messages[index][message_key]["text"].split(" ") + message_tokens = self.tokenize_wifi_msg( + wifi_messages[index][message_key]["text"] + ) if port_name is None: logging.info( f"Device {port_name} is None device name not existed in wifi messages..." @@ -355,7 +369,7 @@ def count_wifi_msg_matches( # logging.info(f"The filter '{match_text}' is present in the Wi-Fi message test list.") matches.append("YES") else: - match_tokens = match_text.split(" ") + match_tokens = self.tokenize_wifi_msg(match_text) if all( token in message_tokens for token in match_tokens ): @@ -367,7 +381,7 @@ def count_wifi_msg_matches( # logging.info(f"The filter '{match_text}' is present in the Wi-Fi message test list.") matches.append("YES") else: - match_tokens = match_text.split(" ") + match_tokens = self.tokenize_wifi_msg(match_text) if all( token in message_tokens for token in match_tokens @@ -376,7 +390,7 @@ def count_wifi_msg_matches( matches.append("YES") else: # if wifi_msg_text is list for message_line in wifi_msg_text: - message_tokens = message_line.split(" ") + message_tokens = self.tokenize_wifi_msg(message_line) # print("$Wifi Message Text list:", message_tokens) if port_name is not None: if message_resource == resource_id: @@ -385,7 +399,7 @@ def count_wifi_msg_matches( # logging.info(f"The filter '{match_text}' is present in the Wi-Fi message test list.") matches.append("YES") else: - match_tokens = match_text.split(" ") + match_tokens = self.tokenize_wifi_msg(match_text) if all( token in message_tokens for token in match_tokens @@ -398,7 +412,9 @@ def count_wifi_msg_matches( # logging.info(f"The filter '{match_text}' is present in the Wi-Fi message test list.") matches.append("YES") else: - match_tokens = match_text.split(" ") + match_tokens = self.tokenize_wifi_msg( + match_text + ) if all( token in message_tokens for token in match_tokens From 0bcd8863a5bfe86bfc31eaea13f2d715a0eee763 Mon Sep 17 00:00:00 2001 From: Narayana-CT Date: Sat, 22 Aug 2026 14:54:51 +0530 Subject: [PATCH 10/13] lf_interop_port_reset_test.py: give every function a short docstring Signed-off-by: Narayana-CT --- py-scripts/lf_interop_port_reset_test.py | 81 ++++++++++++++++++++---- 1 file changed, 68 insertions(+), 13 deletions(-) diff --git a/py-scripts/lf_interop_port_reset_test.py b/py-scripts/lf_interop_port_reset_test.py index de76e8b6c..a8e2839f0 100755 --- a/py-scripts/lf_interop_port_reset_test.py +++ b/py-scripts/lf_interop_port_reset_test.py @@ -108,6 +108,9 @@ def __init__( get_live_view=False, total_floors=0, ): + """Build the test object from CLI settings and prepare the report helpers. + + InteropPortReset("192.168.244.97", ssid="Authtesting", iterations=10)""" super().__init__(lfclient_host=lanforge_ip, lfclient_port=8080) self.total_connects = [] self.total_assoc_rejections = [] @@ -183,10 +186,9 @@ def __init__( # level=logging.INFO, force=True) def json_get_with_retry(self, url, wait_time=40, poll_interval=5, debug_=False): - """ - Calls self.json_get(url), retrying every poll_interval seconds for up - to wait_time seconds if LANforge returns no response. - """ + """Take a LANforge URL and return its JSON response, or None on failure. + + "/port/1/1/eth1?fields=ip" -> {"interface": {"ip": "192.168.1.1"}}""" start_time = time.time() response = self.json_get(url, debug_=debug_) while response is None and (time.time() - start_time) < wait_time: @@ -209,6 +211,9 @@ def change_port_to_ip(self, upstream_port): # for --upstream_port. This is only called once, at test start, and we cannot # proceed without a resolved manager IP, so retry for a while and then # abort instead of silently continuing with an unresolved port name. + """Take an upstream port name and return its IP address as a string. + + "eth1" -> "192.168.1.1"; an IP passed in comes back unchanged""" if upstream_port.count(".") != 3: shelf, resource, port_name, _ = self.name_to_eid(upstream_port) response = self.json_get_with_retry( @@ -233,6 +238,9 @@ def change_port_to_ip(self, upstream_port): def selecting_devices_from_available(self): # If device list is not provided by user, then it shows the available devices to choose from + """Pick the devices to test and store the selection. + + Fills self.final_selected_android_list, e.g. ["1.10", "1.12"]""" if self.device_list is None: configurable_devices = ( self.base_interop_profile.query_all_devices_to_configure_wifi() @@ -295,6 +303,9 @@ def selecting_devices_from_available(self): def create_log_file(self, json_list, file_name="empty.json"): # Convert the list of JSON values to a JSON-formatted string + """Write wifi messages as JSON under the report Wifi_Messages folder. + + ([{...}], "reset_0_log.json") -> Wifi_Messages/reset_0_log.json""" json_string = json.dumps(json_list) new_folder = os.path.join(self.report_path, "Wifi_Messages") if not (os.path.exists(new_folder) and os.path.isdir(new_folder)): @@ -305,6 +316,9 @@ def create_log_file(self, json_list, file_name="empty.json"): file.write(json_string) def remove_files_with_duplicate_names(self, folder_path): + """Delete every file in a folder whose name was already seen. + + "/Wifi_Messages/" -> keeps the first of each name""" file_names = {} for root, _, files in os.walk(folder_path): for file in files: @@ -319,6 +333,9 @@ def remove_files_with_duplicate_names(self, folder_path): file_names[file_name] = file_path def get_last_wifi_msg_timestamp(self): + """Return the newest wifi message time-stamp, or "NA" if unreadable. + + -> "1787389179894", epoch ms, the baseline for one reset""" response = self.json_get_with_retry("/wifi-msgs/last/1", debug_=True) try: last_timestamp = response["wifi-messages"]["time-stamp"] @@ -347,6 +364,9 @@ def tokenize_wifi_msg(self, text): def count_wifi_msg_matches( self, wifi_messages=None, message_keys=None, device_eid=None, match_text=None ): + """Count one device wifi messages containing every word of match_text. + + (msgs, keys, "1.29.en0", "STA is connected") -> 2""" matches = [] eid_parts = device_eid.split(".") port_name = eid_parts[2] @@ -434,6 +454,9 @@ def collect_device_metrics( ): # print("Waiting for 20 sec to fetch the logs...") # time.sleep(20) + """Count one device wifi events since a time-stamp and return metrics. + + -> {"1.29.en0": {"Connected": 1, "Disconnected": 1, ...}}""" wifi_msgs_response = self.json_get_with_retry( "/wifi-msgs/since=time/" + str(since_time), debug_=True ) @@ -918,12 +941,18 @@ def collect_device_metrics( def write_iteration_csvs(self, device_metrics, iteration): # storing results in csv file for each reset + """Write one CSV per device with its metrics for a single iteration. + + ({"1.29.en0": {...}}, 0) -> /1.29.en0_0.csv""" for device_eid, metrics in device_metrics.items(): df = pd.DataFrame([metrics]) filename = f"{self.report_path}/{device_eid}_{iteration}.csv" df.to_csv(filename, index=False) def aggregate_device_metrics(self, per_iteration_results): + """Add up each device counts over all iterations, per device. + + {0: {"eid": {"Connected": 1}}, 1: {...}} -> {"eid": {"Connected": 2}}""" aggregated_metrics = {} for iteration in sorted(per_iteration_results.keys()): if per_iteration_results[iteration] is None: @@ -944,6 +973,9 @@ def aggregate_device_metrics(self, per_iteration_results): return dict(aggregated_metrics) def write_coordinate_csv(self, per_iteration_results, iteration): + """Write the per-device totals for the current coordinate as a CSV. + + -> /overall_reset_.csv; also sets self.result_df""" columns = [ "Client", "ConnectAttempt", @@ -1012,6 +1044,9 @@ def write_coordinate_csv(self, per_iteration_results, iteration): ) def performing_resets(self, test_start_time=None): + """Run every reset iteration and return its metrics with the duration. + + -> ({0: {"1.29.en0": {...}}, 1: {...}}, timedelta 0:05:12)""" iteration_indexes = [] for index in range(self.iterations): iteration_indexes.append(index) @@ -1208,6 +1243,9 @@ def performing_resets(self, test_start_time=None): # @property def run(self): + """Connect the devices, run all resets, return results and duration. + + -> ({0: {"1.29.en0": {...}}, ...}, timedelta 0:05:12)""" try: # start timer test_start = datetime.now() @@ -1453,6 +1491,9 @@ def generate_overall_graph( bar_text_rotation=45, graph_suffix="", ): + """Draw the all-device bar graph and return the image file name. + + -> "overall_graph.png", saved in the report folder""" metric_labels = [ "Port Resets", "Disconnected", @@ -1632,6 +1673,9 @@ def per_client_graph( graph_title_size=16, graph_title="Client %s Performance Port Reset Totals", ): + """Draw one device totals as a bar graph and return the file name. + + ({"Connects": 5}, "per_client_0") -> "per_client_0.png" file""" self.graph_image_name = image_name bar_labels = list(metric_totals.keys()) bar_totals = list(metric_totals.values()) @@ -1689,6 +1733,9 @@ def per_client_graph( return "%s.png" % self.graph_image_name def generate_overall_graph_table(self, per_iteration_results, device_list): + """Total every device counts for the report summary table. + + Fills self.total_connects, self.total_disconnects, one per device""" if self.robot_test: ( self.total_resets, @@ -1782,6 +1829,9 @@ def generate_overall_graph_table(self, per_iteration_results, device_list): def individual_client_info(self, per_iteration_results, device_list): # per client table and graphs # self.total_resets, self.total_disconnects, self.total_scans, self.total_assoc_attempts, self.total_assoc_rejections, self.total_connects = [], [], [], [], [], [] + """Add a per-iteration graph and table for every device to the report. + + (results, ["1.29.en0"]) -> a graph and table per device""" for device_eid, device_index in zip(device_list, range(len(device_list))): iteration_indexes = list(per_iteration_results.keys()) iteration_numbers = [] @@ -1922,6 +1972,9 @@ def individual_client_info(self, per_iteration_results, device_list): self.lf_report.save_csv("overall_report.csv", client_table_df) def generate_report(self, per_iteration_results=None, test_duration=None): + """Build the HTML and PDF report for a normal run. + + (results, timedelta 0:05:12) -> report under self.report_path""" try: # print("per iteration results", per_iteration_results) # print("Test Duration", test_duration) @@ -2088,12 +2141,9 @@ def generate_report(self, per_iteration_results=None, test_duration=None): logging.warning(str(e)) def add_live_view_images_to_report(self): - """ - This function looks for throughput and RSSI images for each floor - in the 'live_view_images' folder within `self.result_dir`. - It waits up to **60 seconds** for each image. If an image is found, - it's added to the `report` on a new page; otherwise, it's skipped. - """ + """Add each floor live-view image to the report, skipping missing ones. + + -> one page per image in /live_view_images/""" for floor in range(0, int(self.total_floors)): port_reset_image_path = os.path.join( self.result_dir, @@ -2119,6 +2169,9 @@ def add_live_view_images_to_report(self): self.lf_report.build_custom() def generate_report_for_robo(self): + """Build the HTML and PDF report for a robot run. + + -> report with coordinate results under self.report_path""" date = str(datetime.now()).split(",")[0].replace(" ", "-").split(".")[0] # self.lf_report.move_data(_file_name="overall_reset_test.log") security = "" @@ -2403,9 +2456,9 @@ def generate_report_for_robo(self): ) def write_overall_csv(self, per_iteration_results): - """ - Aggregate client connection stats from all iterations and save a summary CSV (overall_reset.csv). - """ + """Add up every device counts over all iterations into one CSV. + + {0: {"1.29.en0": {...}}, ...} -> /overall_reset.csv""" totals_per_device = {} for _, iteration_metrics in per_iteration_results.items(): @@ -2455,6 +2508,8 @@ def write_overall_csv(self, per_iteration_results): def main(): + """Parse the command line, run the port reset test, and write its report.""" + help_summary = """\ The LANforge interop port reset test enables users to use real Wi-Fi stations and connect them to the Access Point being tested. It then disconnects and reconnects a given number of stations at different time intervals. From 6148355017e8b04590efd96c1a7dc075b2053072 Mon Sep 17 00:00:00 2001 From: Narayana-CT Date: Sat, 22 Aug 2026 15:08:00 +0530 Subject: [PATCH 11/13] lf_interop_port_reset_test.py: drop debug prints Signed-off-by: Narayana-CT --- py-scripts/lf_interop_port_reset_test.py | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/py-scripts/lf_interop_port_reset_test.py b/py-scripts/lf_interop_port_reset_test.py index a8e2839f0..71edb46a4 100755 --- a/py-scripts/lf_interop_port_reset_test.py +++ b/py-scripts/lf_interop_port_reset_test.py @@ -289,7 +289,6 @@ def selecting_devices_from_available(self): _exit_on_error=False, ) supported_resource_ids = self.interop.supported_devices_resource_id - print("Supported dict", supported_resource_ids) self.final_selected_android_list = [] for device_name in supported_resource_ids.keys(): if device_name != "": @@ -411,7 +410,6 @@ def count_wifi_msg_matches( else: # if wifi_msg_text is list for message_line in wifi_msg_text: message_tokens = self.tokenize_wifi_msg(message_line) - # print("$Wifi Message Text list:", message_tokens) if port_name is not None: if message_resource == resource_id: if port_name in message_tokens: # for android @@ -452,7 +450,6 @@ def collect_device_metrics( file_name="dummy.json", iteration=None, ): - # print("Waiting for 20 sec to fetch the logs...") # time.sleep(20) """Count one device wifi events since a time-stamp and return metrics. @@ -484,7 +481,6 @@ def collect_device_metrics( device_metrics[str(device_eid)]["cx time (us)"] = "NA" self.write_iteration_csvs(device_metrics, iteration) return device_metrics - # print("Wifi msgs Response : ", wifi_messages) logging.info( f"Counting the DISCONNECTIONS, SCANNING, ASSOC ATTEMPTS, ASSOC RECJECTIONS, CONNECTS for device {device_eid}" ) @@ -497,7 +493,6 @@ def collect_device_metrics( f"{wifi_messages['resource']}.{wifi_messages['time-stamp']}": wifi_messages } ] - # print("After Updating Wi-Fi msgs Response : ", wifi_messages) self.create_log_file(json_list=wifi_messages, file_name=file_name) self.remove_files_with_duplicate_names( folder_path=f"{self.report_path}/Wifi_Messages/" @@ -506,7 +501,6 @@ def collect_device_metrics( for index in range(len(wifi_messages)): message_keys.append(list(wifi_messages[index].keys())[0]) - # print("Key list", message_keys) # android (flag) check for clustered lanforge cases is_android = False adb_response = self.json_get_with_retry("/adb/") @@ -1601,7 +1595,6 @@ def generate_overall_graph( metric_totals["Assoc Attempts"] = assoc_attempt_total metric_totals["Connected"] = connect_total metric_totals["Association Rejection"] = assoc_rejection_total - # print("Final data for overall graph: ", metric_totals) # creating the dataset self.graph_image_name = f"overall_graph{graph_suffix}" @@ -1726,9 +1719,7 @@ def per_client_graph( plt.suptitle(graph_title, fontsize=graph_title_size) plt.savefig("%s.png" % self.graph_image_name, dpi=96) # generate csv - print(metric_totals) df = pd.DataFrame(data=metric_totals, index=[1]) - print(df) df.to_csv("{}/{}.csv".format(self.report_path, image_name)) return "%s.png" % self.graph_image_name @@ -1816,8 +1807,6 @@ def generate_overall_graph_table(self, per_iteration_results, device_list): connect_total = connect_total + count metric_totals["Connects"] = connect_total - # print(f"Final data for per client graph for {device_eid}: {metric_totals}") - # fetching the total dissconnects, connects, ass_attemsts, ass_rejections, scans self.total_resets.append(self.iterations) self.total_disconnects.append(sum(disconnected)) @@ -1907,8 +1896,6 @@ def individual_client_info(self, per_iteration_results, device_list): connect_total = connect_total + count metric_totals["Connects"] = connect_total - # print(f"Final data for per client graph for {device_eid}: {metric_totals}") - if "1.1." in device_eid: # setting the title for per client graph and table represent title. android_user_name = self.interop.get_device_details( @@ -1976,8 +1963,6 @@ def generate_report(self, per_iteration_results=None, test_duration=None): (results, timedelta 0:05:12) -> report under self.report_path""" try: - # print("per iteration results", per_iteration_results) - # print("Test Duration", test_duration) # logging.info("per iteration results " + str(per_iteration_results)) date = str(datetime.now()).split(",")[0].replace(" ", "-").split(".")[0] @@ -2500,11 +2485,10 @@ def write_overall_csv(self, per_iteration_results): ).reset_index() summary_df = summary_df.rename(columns={"index": "Client"}) self.result_df = summary_df.copy() - # Save and print + # Save summary_df.to_csv(f"{self.report_path}/overall_reset.csv", index=False) if self.dowebgui: summary_df.to_csv(f"{self.result_dir}/overall_reset.csv", index=False) - print(summary_df) def main(): @@ -2769,7 +2753,6 @@ def main(): port_reset_test.upstream_port ) port_reset_test.base_interop_profile.server_ip = port_reset_test.upstream_port - print(port_reset_test.upstream_port) port_reset_test.selecting_devices_from_available() if port_reset_test.robot_test: From de203240569eac2929455fc0358ba8836476128c Mon Sep 17 00:00:00 2001 From: Narayana-CT Date: Sat, 22 Aug 2026 15:44:32 +0530 Subject: [PATCH 12/13] lf_interop_port_reset_test.py: drop dead and redundant comments Signed-off-by: Narayana-CT --- py-scripts/lf_interop_port_reset_test.py | 92 ++---------------------- 1 file changed, 6 insertions(+), 86 deletions(-) diff --git a/py-scripts/lf_interop_port_reset_test.py b/py-scripts/lf_interop_port_reset_test.py index 71edb46a4..ca61fb211 100755 --- a/py-scripts/lf_interop_port_reset_test.py +++ b/py-scripts/lf_interop_port_reset_test.py @@ -182,8 +182,6 @@ def __init__( ) self.utility = base.UtilityInteropWifi(host_ip=self.lanforge_ip) - # logging.basicConfig(filename='port_reset.log', filemode='w', format='%(asctime)s - %(message)s', - # level=logging.INFO, force=True) def json_get_with_retry(self, url, wait_time=40, poll_interval=5, debug_=False): """Take a LANforge URL and return its JSON response, or None on failure. @@ -237,7 +235,6 @@ def change_port_to_ip(self, upstream_port): return upstream_port def selecting_devices_from_available(self): - # If device list is not provided by user, then it shows the available devices to choose from """Pick the devices to test and store the selection. Fills self.final_selected_android_list, e.g. ["1.10", "1.12"]""" @@ -301,7 +298,6 @@ def selecting_devices_from_available(self): ) def create_log_file(self, json_list, file_name="empty.json"): - # Convert the list of JSON values to a JSON-formatted string """Write wifi messages as JSON under the report Wifi_Messages folder. ([{...}], "reset_0_log.json") -> Wifi_Messages/reset_0_log.json""" @@ -310,7 +306,6 @@ def create_log_file(self, json_list, file_name="empty.json"): if not (os.path.exists(new_folder) and os.path.isdir(new_folder)): os.makedirs(new_folder) file_path = f"{self.report_path}/Wifi_Messages/{file_name}" - # Write the JSON-formatted string to the .json file with open(file_path, "w") as file: file.write(json_string) @@ -324,11 +319,9 @@ def remove_files_with_duplicate_names(self, folder_path): file_path = os.path.join(root, file) file_name = os.path.basename(file_path) if file_name in file_names: - # Removing the duplicate file os.remove(file_path) logging.info(f"Removed duplicate file: {file_path}") else: - # Adding the file name to the dictionary file_names[file_name] = file_path def get_last_wifi_msg_timestamp(self): @@ -385,19 +378,16 @@ def count_wifi_msg_matches( if message_resource == resource_id: if port_name in message_tokens: if match_text in message_tokens: - # logging.info(f"The filter '{match_text}' is present in the Wi-Fi message test list.") matches.append("YES") else: match_tokens = self.tokenize_wifi_msg(match_text) if all( token in message_tokens for token in match_tokens ): - # logging.info(f"The filter {match_tokens} sequence is present in Wi-Fi msg.") matches.append("YES") else: - if f"IFNAME={port_name}" in message_tokens: # for linux + if f"IFNAME={port_name}" in message_tokens: if match_text in message_tokens: - # logging.info(f"The filter '{match_text}' is present in the Wi-Fi message test list.") matches.append("YES") else: match_tokens = self.tokenize_wifi_msg(match_text) @@ -405,16 +395,14 @@ def count_wifi_msg_matches( token in message_tokens for token in match_tokens ): - # logging.info(f"The filter {match_tokens} sequence is present in Wi-Fi msg.") matches.append("YES") else: # if wifi_msg_text is list for message_line in wifi_msg_text: message_tokens = self.tokenize_wifi_msg(message_line) if port_name is not None: if message_resource == resource_id: - if port_name in message_tokens: # for android + if port_name in message_tokens: if match_text in message_tokens: - # logging.info(f"The filter '{match_text}' is present in the Wi-Fi message test list.") matches.append("YES") else: match_tokens = self.tokenize_wifi_msg(match_text) @@ -422,12 +410,10 @@ def count_wifi_msg_matches( token in message_tokens for token in match_tokens ): - # logging.info(f"The filter {match_tokens} sequence is present in Wi-Fi msg.") matches.append("YES") else: - if f"IFNAME={port_name}" in message_tokens: # for linux + if f"IFNAME={port_name}" in message_tokens: if match_text in message_tokens: - # logging.info(f"The filter '{match_text}' is present in the Wi-Fi message test list.") matches.append("YES") else: match_tokens = self.tokenize_wifi_msg( @@ -437,7 +423,6 @@ def count_wifi_msg_matches( token in message_tokens for token in match_tokens ): - # logging.info(f"The filter {match_tokens} sequence is present in Wi-Fi msg.") matches.append("YES") match_count = matches.count("YES") return match_count @@ -450,7 +435,6 @@ def collect_device_metrics( file_name="dummy.json", iteration=None, ): - # time.sleep(20) """Count one device wifi events since a time-stamp and return metrics. -> {"1.29.en0": {"Connected": 1, "Disconnected": 1, ...}}""" @@ -541,7 +525,6 @@ def collect_device_metrics( logging.info( f"Disconnect Count For Android: {android_disconnect_count}" ) - # Updating the dict with disconnects for android logging.info( "Final Disconnect count for %s: %s" % (device_eid, android_disconnect_count) @@ -607,16 +590,13 @@ def collect_device_metrics( ) android_connected_count = 0 logging.info(f"Connected Count for Android: {android_connected_count}") - # Updating the dict with connects for android logging.info( "Final Connected Count for %s: %s" % (device_eid, android_connected_count) ) device_metrics[str(device_eid)]["Connected"] = android_connected_count - # Adding remarks remarks = "NA" device_metrics[str(device_eid)]["Remarks"] = remarks - # Updating the association-rejections if android_association_attempt > android_connected_count: android_association_rejection = ( android_association_attempt - android_connected_count @@ -714,7 +694,6 @@ def collect_device_metrics( win_connection_state_unverified = False # assoc-rejection based logic if win_association_rejection: - # Updating the connects actual_connects = ( win_association_attempt - win_association_rejection ) @@ -753,7 +732,6 @@ def collect_device_metrics( % (device_eid, win_connected_count) ) device_metrics[str(device_eid)]["Connected"] = win_connected_count - # Updating the association-rejections if win_association_attempt > win_connected_count: win_association_rejection = ( win_association_attempt - win_connected_count @@ -761,7 +739,6 @@ def collect_device_metrics( device_metrics[str(device_eid)][ "Association Rejection" ] = win_association_rejection - # Adding re-marks remarks = "NA" if win_disconnect_count == 0 and win_connected_count == 1: remarks = "No Disconnections are seen but Client is UP and connected to user given SSID." @@ -853,7 +830,6 @@ def collect_device_metrics( linux_mac_connection_state_unverified = False # assoc-rejection based logic if linux_mac_association_rejection: - # Updating the connects actual_connects = ( linux_mac_association_attempt - linux_mac_association_rejection ) @@ -895,7 +871,6 @@ def collect_device_metrics( % (device_eid, linux_mac_connected_count) ) device_metrics[str(device_eid)]["Connected"] = linux_mac_connected_count - # Updating the association-rejections if linux_mac_association_attempt > linux_mac_connected_count: linux_mac_association_rejection = ( linux_mac_association_attempt - linux_mac_connected_count @@ -903,7 +878,6 @@ def collect_device_metrics( device_metrics[str(device_eid)][ "Association Rejection" ] = linux_mac_association_rejection - # Adding remarks remarks = "NA" if linux_mac_disconnect_count == 0 and linux_mac_connected_count == 1: remarks = "No Disconnections are seen but Client is UP and connected to user given SSID." @@ -934,7 +908,6 @@ def collect_device_metrics( return device_metrics def write_iteration_csvs(self, device_metrics, iteration): - # storing results in csv file for each reset """Write one CSV per device with its metrics for a single iteration. ({"1.29.en0": {...}}, 0) -> /1.29.en0_0.csv""" @@ -1102,13 +1075,9 @@ def performing_resets(self, test_start_time=None): empty_metrics = dict.fromkeys(metric_names) for device_eid in self.adb_device_list: - device_metrics[device_eid] = ( - empty_metrics.copy() - ) # for android devices dict + device_metrics[device_eid] = empty_metrics.copy() for device_eid in self.all_laptops: - laptop_metrics[device_eid] = ( - empty_metrics.copy() - ) # for laptop devices dict + laptop_metrics[device_eid] = empty_metrics.copy() logging.info(f"Final Outcome dict for android devices: {device_metrics}") logging.info(f"Final Outcome dict for laptop devices: {laptop_metrics}") logging.info(str(device_metrics)) @@ -1216,7 +1185,6 @@ def performing_resets(self, test_start_time=None): ) else: logging.info(f"Test Ended at {test_end}") - # logging.info("Test ended at " + test_end_time) time_format = "%b %d %H:%M:%S" test_duration = datetime.strptime( test_end_time, time_format @@ -1235,13 +1203,11 @@ def performing_resets(self, test_start_time=None): return per_iteration_results, test_duration - # @property def run(self): """Connect the devices, run all resets, return results and duration. -> ({0: {"1.29.en0": {...}}, ...}, timedelta 0:05:12)""" try: - # start timer test_start = datetime.now() test_start_time = test_start.strftime("%b %d %H:%M:%S") logging.info(f"Test Started at {test_start}") @@ -1295,7 +1261,6 @@ def run(self): f"Separated device names from the full name: {self.android_serials}" ) - # check status of devices phantom_states = [] for device_eid in self.adb_device_list: phantom_states.append( @@ -1380,7 +1345,6 @@ def run(self): logging.info(f"Health Status for the Android Devices: {android_health}") logging.info(f"Health Status for the Laptop Devices: {laptop_health}") - # Resting Starts from here if not self.robot_test: per_iteration_results, test_duration = self.performing_resets( test_start_time=test_start_time @@ -1568,7 +1532,6 @@ def generate_overall_graph( assoc_attempt_counts = assoc_attempt_counts + laptop_assoc_attempt_counts assoc_rejection_counts = assoc_rejection_counts + laptop_assoc_rejection_counts - # count connects and disconnects scan_total, assoc_attempt_total = 0, 0 for index, _ in zip(range(len(scan_counts)), range(len(assoc_attempt_counts))): for count in scan_counts[index]: @@ -1596,7 +1559,6 @@ def generate_overall_graph( metric_totals["Connected"] = connect_total metric_totals["Association Rejection"] = assoc_rejection_total - # creating the dataset self.graph_image_name = f"overall_graph{graph_suffix}" bar_labels = list(metric_totals.keys()) bar_totals = list(metric_totals.values()) @@ -1612,7 +1574,6 @@ def generate_overall_graph( yaxis_visible = True ax.yaxis.set_visible(yaxis_visible) - # creating the bar plot colors = ("#f56122", "#00FF00", "#f5ea22", "#3D85C6", "#fa4d4d", "forestgreen") for bar_total, color, index in zip(bar_totals, colors, range(len(bar_labels))): plt.bar(bar_labels[index], bar_total, color=color, width=bar_width) @@ -1673,7 +1634,6 @@ def per_client_graph( bar_labels = list(metric_totals.keys()) bar_totals = list(metric_totals.values()) - # fig = plt.figure(figsize=(12, 4)) fig, ax = plt.subplots(figsize=figsize, gridspec_kw=_alignment) # to remove the borders if remove_border is not None: @@ -1685,7 +1645,6 @@ def per_client_graph( yaxis_visible = True ax.yaxis.set_visible(yaxis_visible) - # creating the bar plot colors = ("#f56122", "#00FF00", "#f5ea22", "#3D85C6", "#fa4d4d", "forestgreen") for bar_total, color, index in zip(bar_totals, colors, range(len(bar_labels))): plt.bar(bar_labels[index], bar_total, color=color, width=bar_width) @@ -1718,7 +1677,6 @@ def per_client_graph( ) plt.suptitle(graph_title, fontsize=graph_title_size) plt.savefig("%s.png" % self.graph_image_name, dpi=96) - # generate csv df = pd.DataFrame(data=metric_totals, index=[1]) df.to_csv("{}/{}.csv".format(self.report_path, image_name)) return "%s.png" % self.graph_image_name @@ -1770,7 +1728,6 @@ def generate_overall_graph_table(self, per_iteration_results, device_list): ) remarks.append(per_iteration_results[iteration][device_eid]["Remarks"]) - # graph calculation metric_labels = [ "Port Resets", "Disconnects", @@ -1807,7 +1764,6 @@ def generate_overall_graph_table(self, per_iteration_results, device_list): connect_total = connect_total + count metric_totals["Connects"] = connect_total - # fetching the total dissconnects, connects, ass_attemsts, ass_rejections, scans self.total_resets.append(self.iterations) self.total_disconnects.append(sum(disconnected)) self.total_scans.append(sum(scanning)) @@ -1816,8 +1772,6 @@ def generate_overall_graph_table(self, per_iteration_results, device_list): self.total_connects.append(sum(connected)) def individual_client_info(self, per_iteration_results, device_list): - # per client table and graphs - # self.total_resets, self.total_disconnects, self.total_scans, self.total_assoc_attempts, self.total_assoc_rejections, self.total_connects = [], [], [], [], [], [] """Add a per-iteration graph and table for every device to the report. (results, ["1.29.en0"]) -> a graph and table per device""" @@ -1859,7 +1813,6 @@ def individual_client_info(self, per_iteration_results, device_list): per_iteration_results[iteration][device_eid]["cx time (us)"] ) - # graph calculation metric_labels = [ "Port Resets", "Disconnects", @@ -1897,7 +1850,6 @@ def individual_client_info(self, per_iteration_results, device_list): metric_totals["Connects"] = connect_total if "1.1." in device_eid: - # setting the title for per client graph and table represent title. android_user_name = self.interop.get_device_details( device=device_eid, query="user-name" ) @@ -1913,7 +1865,6 @@ def individual_client_info(self, per_iteration_results, device_list): ) self.lf_report.build_objective() else: - # setting the title for per client graph and table represent title. self.lf_report.set_obj_html( "Port Resets for Client " + str(device_eid) + ".", "The below table & graph displays details of " @@ -1922,7 +1873,6 @@ def individual_client_info(self, per_iteration_results, device_list): ) self.lf_report.build_objective() - # per client graph generation client_graph = self.per_client_graph( metric_totals=metric_totals, image_name="per_client_" + str(device_index), @@ -1937,12 +1887,10 @@ def individual_client_info(self, per_iteration_results, device_list): + str(device_eid) + " Total Reset Performance Graph", ) - # graph1 = self.generate_per_station_graph() self.lf_report.set_graph_image(client_graph) self.lf_report.move_graph_image() self.lf_report.build_graph() - # per client table data per_iteration_table = { "Reset Count": iteration_numbers, "Disconnected": disconnected, @@ -1963,7 +1911,6 @@ def generate_report(self, per_iteration_results=None, test_duration=None): (results, timedelta 0:05:12) -> report under self.report_path""" try: - # logging.info("per iteration results " + str(per_iteration_results)) date = str(datetime.now()).split(",")[0].replace(" ", "-").split(".")[0] security = "" @@ -1982,7 +1929,6 @@ def generate_report(self, per_iteration_results=None, test_duration=None): "Security": security, "Total Reset Count": self.iterations, "No of Clients": f"{len(self.all_selected_devices)} (Windows: {len(self.windows_list)}, Linux: {len(self.linux_list)}, Mac: {len(self.mac_list)}, Android: {len(self.adb_device_list)})", # noqa: E501 - # "Wait Time": str(self.wait_time) + " sec", "Time interval between resets": str(self.reset_interval_sec) + " sec", "Test Duration": test_duration, } @@ -2019,7 +1965,6 @@ def generate_report(self, per_iteration_results=None, test_duration=None): "4. Association Attempts: Total number of association attempts (Associating state) made by all clients after WiFi is re-enabled in the full test.
" "4. Association Rejections: Total number of association rejections made by all clients after WiFi is re-enabled in the full test.
" "6. Connected: Total number of successful connections (Associated state) achieved by all clients during the test when WiFi is re-enabled.
", - # " Here real clients used is "+ str(self.clients) + "and number of resets provided is " + str(self.iterations) ) self.lf_report.build_objective() overall_graph = self.generate_overall_graph( @@ -2033,7 +1978,6 @@ def generate_report(self, per_iteration_results=None, test_duration=None): _legend_box=(0.5, -0.06), text_font=12, ) - # graph1 = self.generate_per_station_graph() self.lf_report.set_graph_image(overall_graph) self.lf_report.move_graph_image() self.lf_report.build_graph() @@ -2093,8 +2037,6 @@ def generate_report(self, per_iteration_results=None, test_duration=None): "Name of the Devices": device_names, "Hardware Version": user_names, "Device Type": device_types, - # "Model": model, - # "SDK Release": release, "Port Resets": self.total_resets, "Disconnects": self.total_disconnects, "Scans": self.total_scans, @@ -2108,9 +2050,6 @@ def generate_report(self, per_iteration_results=None, test_duration=None): self.individual_client_info( per_iteration_results=per_iteration_results, device_list=all_devices ) - # self.lf_report.set_obj_html("Tested Clients Information:", - # "The table displays details of real clients which are involved in the test.") - # self.lf_report.build_objective() self.lf_report.build_footer() self.lf_report.write_html() @@ -2121,7 +2060,6 @@ def generate_report(self, per_iteration_results=None, test_duration=None): _page_size="A4", _orientation="Portrait" ) - # self.lf_report.move_data(directory="log", _file_name="port_reset.log") except Exception as e: logging.warning(str(e)) @@ -2158,7 +2096,6 @@ def generate_report_for_robo(self): -> report with coordinate results under self.report_path""" date = str(datetime.now()).split(",")[0].replace(" ", "-").split(".")[0] - # self.lf_report.move_data(_file_name="overall_reset_test.log") security = "" if self.encryption == "psk2": security = "wpa2" @@ -2175,7 +2112,6 @@ def generate_report_for_robo(self): "Security": security, "Total Reset Count": self.iterations, "No of Clients": f"{len(self.all_selected_devices)} (Windows: {len(self.windows_list)}, Linux: {len(self.linux_list)}, Mac: {len(self.mac_list)}, Android: {len(self.adb_device_list)})", # noqa: E501 - # "Wait Time": str(self.wait_time) + " sec", "Time interval between resets": str(self.reset_interval_sec) + " sec", } test_setup_info["Selected Coordinates"] = self.coordinate @@ -2217,7 +2153,6 @@ def generate_report_for_robo(self): "4. Association Attempts: Total number of association attempts (Associating state) made by all clients after WiFi is re-enabled in the full test.
" "4. Association Rejections: Total number of association rejections made by all clients after WiFi is re-enabled in the full test.
" "6. Connected: Total number of successful connections (Associated state) achieved by all clients during the test when WiFi is re-enabled.
", - # " Here real clients used is "+ str(self.clients) + "and number of resets provided is " + str(self.iterations) ) self.lf_report.build_objective() for coordinate_index in range(len(self.coordinate_list)): @@ -2255,7 +2190,6 @@ def generate_report_for_robo(self): text_font=12, graph_suffix=graph_suffix, ) - # graph1 = self.generate_per_station_graph() self.lf_report.set_graph_image(overall_graph) self.lf_report.move_graph_image() self.lf_report.build_graph() @@ -2318,8 +2252,6 @@ def generate_report_for_robo(self): "Name of the Devices": device_names, "Hardware Version": user_names, "Device Type": device_types, - # "Model": model, - # "SDK Release": release, "Port Resets": self.total_resets, "Disconnects": self.total_disconnects, "Scans": self.total_scans, @@ -2359,7 +2291,6 @@ def generate_report_for_robo(self): text_font=12, graph_suffix=graph_suffix, ) - # graph1 = self.generate_per_station_graph() self.lf_report.set_graph_image(overall_graph) self.lf_report.move_graph_image() self.lf_report.build_graph() @@ -2419,8 +2350,6 @@ def generate_report_for_robo(self): "Name of the Devices": device_names, "Hardware Version": user_names, "Device Type": device_types, - # "Model": model, - # "SDK Release": release, "Port Resets": self.total_resets, "Disconnects": self.total_disconnects, "Scans": self.total_scans, @@ -2479,13 +2408,11 @@ def write_overall_csv(self, per_iteration_results): ) totals_per_device[device_eid]["Iterations"] += 1 - # Create DataFrame summary_df = pd.DataFrame.from_dict( totals_per_device, orient="index" ).reset_index() summary_df = summary_df.rename(columns={"index": "Client"}) self.result_df = summary_df.copy() - # Save summary_df.to_csv(f"{self.report_path}/overall_reset.csv", index=False) if self.dowebgui: summary_df.to_csv(f"{self.result_dir}/overall_reset.csv", index=False) @@ -2493,7 +2420,7 @@ def write_overall_csv(self, per_iteration_results): def main(): """Parse the command line, run the port reset test, and write its report.""" - + help_summary = """\ The LANforge interop port reset test enables users to use real Wi-Fi stations and connect them to the Access Point being tested. It then disconnects and reconnects a given number of stations at different time intervals. @@ -2625,8 +2552,6 @@ def main(): default=None, action="store_true", ) - # parser.add_argument("--wait_time", type=int, default=20, - # help='Specify the wait time in seconds for WIFI Supplicant Logs.') parser.add_argument( "--android_releases", @@ -2636,7 +2561,6 @@ def main(): "devices on any other release are skipped. Laptops are unaffected. " "eg:- --android_releases 11 12 13", ) - # logging configuration: parser.add_argument( "--log_level", default=None, @@ -2708,18 +2632,15 @@ def main(): ) args = parser.parse_args() - # help summary if args.help_summary: print(help_summary) exit(0) - # set the logger level to debug logger_config = lf_logger_config.lf_logger_config() if args.log_level: logger_config.set_level(level=args.log_level) if args.lf_logger_config_json: - # logger_config.lf_logger_config_json = "lf_logger_config.json" logger_config.lf_logger_config_json = args.lf_logger_config_json logger_config.load_lf_logger_config() @@ -2731,7 +2652,6 @@ def main(): passwd=args.passwd, encryption=args.encryp, iterations=args.iterations, - # clients=args.clients, reset_interval_sec=args.reset_interval, android_releases=args.android_releases, upstream_port=args.upstream_port, From 4aaa40a745eeca12a9da20546107f1945482cb91 Mon Sep 17 00:00:00 2001 From: Narayana-CT Date: Sun, 23 Aug 2026 11:41:51 +0530 Subject: [PATCH 13/13] lf_interop_port_reset_test.py: count wifi events on macOS Verified CLI: python3 lf_interop_port_reset_test.py \ --lanforge_ip 192.168.245.117 \ --upstream_port eth2 \ --dut 'Testing_wpa2 AP' \ --ssid Testing_wpa2 --encryp psk2 --passwd lanforge \ --iterations 2 --reset_interval 5 \ --android_releases 13 16 \ --device_list 08301JEC207624,13301JEC205162,R9ZY30RD0KW,user-ThinkPad-T450,Macs-MacBook-Air.local,user-HP-ProBook-445R-G6 \ --test_name pr_manual_robo \ --robot_test --coordinate P1 \ --robot_ip 127.0.0.1:6000 python3 lf_interop_port_reset_test.py \ --lanforge_ip 192.168.245.117 \ --upstream_port eth2 \ --dut 'Testing_wpa2 AP' \ --ssid Testing_wpa2 --encryp psk2 --passwd lanforge \ --iterations 2 --reset_interval 5 \ --android_releases 13 16 \ --device_list 08301JEC207624,13301JEC205162,R9ZY30RD0KW,user-ThinkPad-T450,Macs-MacBook-Air.local,user-HP-ProBook-445R-G6 \ --test_name pr_manual_rot1 \ --robot_test --coordinate P1 \ --robot_ip 127.0.0.1:6000 \ --rotation 0,90,180 python3 lf_interop_port_reset_test.py \ --lanforge_ip 192.168.245.117 \ --upstream_port eth2 \ --dut 'Testing_wpa2 AP' \ --ssid Testing_wpa2 --encryp psk2 --passwd lanforge \ --iterations 2 --reset_interval 5 \ --android_releases 13 16 \ --device_list 08301JEC207624,13301JEC205162,R9ZY30RD0KW,user-ThinkPad-T450,Macs-MacBook-Air.local,user-HP-ProBook-445R-G6 \ --test_name pr_manual_rot2 \ --robot_test --coordinate P1 \ --robot_ip 127.0.0.1:6000 \ --rotation 45,135,225,315 python3 lf_interop_port_reset_test.py \ --lanforge_ip 192.168.245.117 \ --upstream_port eth2 \ --dut 'Testing_wpa2 AP' \ --ssid Testing_wpa2 --encryp psk2 --passwd lanforge \ --iterations 2 --reset_interval 5 \ --android_releases 13 16 \ --device_list 08301JEC207624,13301JEC205162,R9ZY30RD0KW,user-ThinkPad-T450,DesktopLatitude5490,Macs-MacBook-Air.local,user-HP-ProBook-445R-G6 \ --test_name pr_manual_normal Signed-off-by: Narayana-CT --- py-scripts/lf_interop_port_reset_test.py | 71 ++++++++++++++++++++---- 1 file changed, 61 insertions(+), 10 deletions(-) diff --git a/py-scripts/lf_interop_port_reset_test.py b/py-scripts/lf_interop_port_reset_test.py index ca61fb211..2f90e3f1d 100755 --- a/py-scripts/lf_interop_port_reset_test.py +++ b/py-scripts/lf_interop_port_reset_test.py @@ -221,7 +221,7 @@ def change_port_to_ip(self, upstream_port): upstream_port = response["interface"]["ip"] except (TypeError, KeyError) as e: logging.error( - f"change_port_to_ip: could not resolve upstream port '{upstream_port}' to an IP; LANforge " + f"Could not resolve upstream port '{upstream_port}' to an IP; LANforge " f"response is not in expected format ({e}). Data received: {response}" ) logging.critical( @@ -333,7 +333,7 @@ def get_last_wifi_msg_timestamp(self): last_timestamp = response["wifi-messages"]["time-stamp"] except (TypeError, KeyError) as e: logging.error( - f"get_last_wifi_msg_timestamp: LANforge response is not in expected format ({e}). Data received: {response}" + f"LANforge response is not in expected format ({e}). Data received: {response}" ) logging.warning( "Could not establish a wifi-msgs baseline timestamp; falling back to 'NA' for this reset." @@ -445,7 +445,7 @@ def collect_device_metrics( wifi_messages = wifi_msgs_response["wifi-messages"] except (TypeError, KeyError) as e: logging.error( - f"collect_device_metrics: LANforge response is not in expected format ({e}) while fetching " + f"LANforge response is not in expected format ({e}) while fetching " f"wifi-msgs for device {device_eid}. Data received: {wifi_msgs_response}" ) logging.warning( @@ -492,7 +492,7 @@ def collect_device_metrics( adb_devices = adb_response["devices"] except (TypeError, KeyError) as e: logging.error( - f"collect_device_metrics: LANforge response is not in expected format ({e}) while fetching " + f"LANforge response is not in expected format ({e}) while fetching " f"/adb/ devices. Data received: {adb_response}" ) logging.warning( @@ -621,7 +621,7 @@ def collect_device_metrics( device_metrics[str(device_eid)]["cx time (us)"] = cx_time_us except (TypeError, KeyError) as e: logging.error( - f"collect_device_metrics: could not fetch cx time (us) for device {device_eid}; LANforge " + f"Could not fetch cx time (us) for device {device_eid}; LANforge " f"response is not in expected format ({e}). resource-id response: {resource_id_response}, " f"port response: {port_response}" ) @@ -721,7 +721,7 @@ def collect_device_metrics( win_connected_count = 0 except (TypeError, KeyError) as e: logging.error( - f"collect_device_metrics: could not verify connection state for device " + f"Could not verify connection state for device " f"{device_eid}; LANforge response is not in expected format ({e}). Data " f"received: {port_response}" ) @@ -757,13 +757,64 @@ def collect_device_metrics( device_metrics[str(device_eid)]["cx time (us)"] = cx_time_us except (TypeError, KeyError) as e: logging.error( - f"collect_device_metrics: could not fetch cx time (us) for device {device_eid}; " + f"Could not fetch cx time (us) for device {device_eid}; " f"LANforge response is not in expected format ({e}). Data received: {port_response}" ) device_metrics[str(device_eid)]["cx time (us)"] = "NA" else: device_metrics[str(device_eid)]["cx time (us)"] = "NA" - else: # other means (for linux, mac) + elif device_eid in self.mac_list: # for macOS + mac_disconnect_count = self.count_wifi_msg_matches( + wifi_messages=wifi_messages, + message_keys=message_keys, + device_eid=device_eid, + match_text="disconnected", + ) + logging.info( + "Final Disconnect count for %s: %s" + % (device_eid, mac_disconnect_count) + ) + device_metrics[device_eid]["Disconnected"] = mac_disconnect_count + + mac_connected_count = self.count_wifi_msg_matches( + wifi_messages=wifi_messages, + message_keys=message_keys, + device_eid=device_eid, + match_text="STA is connected", + ) + logging.info( + "Final Connected count for %s: %s" + % (device_eid, mac_connected_count) + ) + device_metrics[str(device_eid)]["Connected"] = mac_connected_count + device_metrics[str(device_eid)]["Scanning"] = 0 + device_metrics[str(device_eid)]["ConnectAttempt"] = 0 + device_metrics[str(device_eid)]["Association Rejection"] = 0 + + remarks = "NA" + if mac_disconnect_count == 0 and mac_connected_count >= 1: + remarks = "No Disconnections are seen but Client is UP and connected to user given SSID." + elif mac_disconnect_count >= 1 and mac_connected_count == 0: + remarks = "The Disconnections are seen but Client did not connected to user given SSID." + device_metrics[str(device_eid)]["Remarks"] = remarks + + if mac_connected_count > 0: + eid_parts = device_eid.split(".") + port_response = self.json_get_with_retry( + f"port/{eid_parts[0]}/{eid_parts[1]}/{eid_parts[2]}?fields=cx time (us)" + ) + try: + cx_time_us = port_response["interface"]["cx time (us)"] + device_metrics[str(device_eid)]["cx time (us)"] = cx_time_us + except (TypeError, KeyError) as e: + logging.error( + f"Could not fetch cx time (us) for device {device_eid}; " + f"LANforge response is not in expected format ({e}). Data received: {port_response}" + ) + device_metrics[str(device_eid)]["cx time (us)"] = "NA" + else: + device_metrics[str(device_eid)]["cx time (us)"] = "NA" + else: # other means (for linux) linux_mac_disconnect_count = self.count_wifi_msg_matches( wifi_messages=wifi_messages, message_keys=message_keys, @@ -860,7 +911,7 @@ def collect_device_metrics( linux_mac_connected_count = 0 except (TypeError, KeyError) as e: logging.error( - f"collect_device_metrics: could not verify connection state for device " + f"Could not verify connection state for device " f"{device_eid}; LANforge response is not in expected format ({e}). Data " f"received: {port_response}" ) @@ -896,7 +947,7 @@ def collect_device_metrics( device_metrics[str(device_eid)]["cx time (us)"] = cx_time_us except (TypeError, KeyError) as e: logging.error( - f"collect_device_metrics: could not fetch cx time (us) for device {device_eid}; " + f"Could not fetch cx time (us) for device {device_eid}; " f"LANforge response is not in expected format ({e}). Data received: {port_response}" ) device_metrics[str(device_eid)]["cx time (us)"] = "NA"