########################################################################### # # Copyright (c) 2019-2021 Diality Inc. - All Rights Reserved. # # THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN # WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. # # @file utils.py # # @author (last) Joseph varghese # @date (last) 15-Jan-2022 # ############################################################################ import sys import test import squish import csv from builtins import format from datetime import datetime from configuration import config from builtins import int as pyInt def start_application(app_name): """ Function to start application and verify application status [running] If application does not start or running status is false, test stops Argument: @param app_name : (str) - Name of the application @param app_executable : (str) - Actual application @return: handle for the application if the application is in running state, or error (exist the application) """ counter = 0 while True: try: counter += 1 test.log("Starting {}".format(app_name)) squish.startApplication(app_name) if counter == 1: test.log("Application launched at the "+str(counter)+" st try.") elif counter == 2: test.log("Application launched at the "+str(counter)+" nd try.") elif counter == 3: test.log("Application launched at the "+str(counter)+" rd try.") else: test.log("Application launched at the "+str(counter)+" th try.") break except RuntimeError: if counter == 1: test.log("Application failed to launch after "+str(counter)+" try - Please refer logs") elif counter == 20: test.log("Exiting after "+str(counter)+ " tries..") sys.exit(1) else: test.log("Application failed to launch after "+str(counter)+ " tries - Please refer logs") except: logErrorDetails("Failed to start the application") sys.exit(1) def check_if_object_is_within_the_container(obj=None, container=None): """ check if an object is inside a container @param obj - child UI object @param container - container UI object @return boolean true/false """ container = squish.findObject(container) containerPos = container.mapToGlobal(squish.QPoint(0, 0)) container_x, container_y = pyInt(containerPos.x), pyInt(containerPos.y) container_width, container_height = pyInt(container.width), pyInt(container.height) obj = squish.findObject(obj) objPos = obj.mapToGlobal(squish.QPoint(0, 0)) obj_x, obj_y = pyInt(objPos.x), pyInt(objPos.y) obj_width, obj_height = pyInt(obj.width), pyInt(obj.height) if obj_x >= container_x and obj_y >= container_y: if (obj_x + obj_width) <= (container_x + container_width) and (obj_y + obj_height) <= (container_y + container_height): return True return False def scroll_to_zone(zone=None, screen_object=None): """ scroll to the numeric if object is hidden @param zone - UI object @param screen_object - UI object (UI Home screen = waveforms + numerics) @return boolean true/false """ counter = 0 while counter <= 100: try: counter += 1 squish.findObject(zone) squish.snooze(0.5) if check_if_object_is_within_the_container(obj=zone, container=screen_object): return True else: raise RuntimeError except RuntimeError: ScreenObj = squish.waitForObject(screen_object) screenHeight = pyInt(ScreenObj.height) screenWidth = pyInt(ScreenObj.width) squish.mouseWheel(ScreenObj, screenWidth-1000, screenHeight-10, 0, -50, squish.Qt.NoModifier) raise LookupError("zone object is not in view to the user after " + \ "trying 100 times") def get_current_date_and_time(date_format='%Y/%b/%d - %H:%M:%S'): date = datetime.now() return str(date.strftime(date_format)) def is_float(num): """ This function checks the value is adaptable for float conversion. @param num - (string) input value for conversion. @return True/False- (bool) returns True if the value can type casted into float, else False """ try: if '.' in num: float(num) return True except ValueError: return False def is_intiger(num): """ This function checks the value is adaptable for integer conversion. @param num - (string) (string) input value for conversion. @return True/False- (bool) returns True if the value can type casted into int, else False """ try: if num.isdigit(): return True except ValueError: return False def get_extracted_file(): """ This function is the handler for getting file from log folder. Application log file is automatically created on '/home/denali/Desktop/sd-card/log/ {current_date}_denaliSquish.log' @return latest_file - (string) returns latest file that append on log folder from sd-data """ try: current_date = get_current_date_and_time(date_format = "%Y_%m_%d") latest_file = '/home/denali/Desktop/sd-card/log/'+current_date+'_denaliSquish.log' return latest_file except: return False def get_extracted_error_file(): """ This function is the handler for getting error file from service folder. Application log file is automatically created on '/home/denali/Desktop/sd-card/service/ {current_date}_denaliSquish.err ' @return latest_file - (string) returns latest file that append on log folder from service """ try: current_date = get_current_date_and_time(date_format = "%Y_%m_%d") latest_file = '/home/denali/Desktop/sd-card/service/'+current_date+'_denaliSquish.err' return latest_file except: return False def get_message_from_log(file_name, message_text): """ This method intended to extract the message from application log. For row[index], index represent column to be extracted. @param file_name - (string) path of the latest log file created. @param message_text - (string) message text to be extracted. @return message - (list) API arguments displayed in log. """ message = [] count = 0 try: with open(file_name, 'r') as csv_file: try: for row in reversed(list(csv.reader(csv_file))): if row[0].isalpha(): pass else: row_length = sum(1 for values in row) if row_length >= 4: if row[3]!= None and row[3] == message_text: if count == 30: test.fail("handler unable to find message text from log file.") message_length = sum(1 for values in row) for column in range(4, message_length, 1): message.append(row[column]) count +=1 for value in range(len(message)): float_status = is_float(message[value]) int_status = is_intiger(message[value]) if float_status is True: message[value] = float(message[value]) if int_status is True: message[value] = int(message[value]) return message else: pass except: test.fail("application log data is corrupted") except: test.fail("Log file is not created or log file is not created based on standard log naming format.") def get_ack_request_details(file_name, message_text): """ This method intended to extract acknowledgement request status, negative requested acknowledgement and message id from application log. For row[index], were index represent column to be extracted. @param file_name - (string) path of the latest log file created. @param message_text - (string) message text to be extracted from log. @return row[3] - (string) acknowledgement request status. @return row[4] - (string) Negative requested acknowledgement value (Sq). @return message_id - (string) formatted message id from log. """ try: message_id = " ID" with open(file_name, 'r') as csv_file: try: for row in reversed(list(csv.reader(csv_file))): if row[0].isalpha(): pass else: row_length = sum(1 for values in row) if row_length == 6 and row[3] != message_text: if row[5].split(':')[0] == message_id: extracted_message_id = pyInt(row[5].split(':')[1], 16) formatted_message_id = format(extracted_message_id, '#0x') # MSG_ID_HD_DEBUG_EVENT (0xFFF1) and MSG_ID_DG_DEBUG_EVENT (0xFFF2) hex values are reversed in log. string_format_id = str(formatted_message_id) first_two_char = string_format_id[2:4] last_two_char = string_format_id[4:6] if last_two_char != '00' and len(string_format_id) != 5: return row[3], row[4], ('0x'+last_two_char+first_two_char) else: return row[3], row[4], string_format_id.replace("00", "") else: pass except: test.fail("application log data is corrupted - unable to fetch data") except: test.fail("Log file is not created or log file is not created based on standard log naming format.") def get_bak_request_details(file_name, ack_bak_value): """ This method intended to extract the acknowledgement back status from application log. For row[index], were index represent column to be extracted. @param file_name - (string) path of the latest log file created. @param ack_bak_value - (string) Positive back acknowledgement value (Sq). @return row[3] - (string) acknowledgement back status. """ try: with open(file_name, 'r') as csv_file: try: for row in reversed(list(csv.reader(csv_file))): if row[0].isalpha(): pass else: row_length = sum(1 for values in row) if row_length >= 5: if row[4] == ack_bak_value: return row[3] else: pass else: pass except: test.fail("application log data is corrupted") except: test.fail("Log file is not created or log file is not created based on standard log naming format.") def get_current_log_details(message_ack = False, message_text = None): """ This function is capable to perform data analysis from application log folder. logs are automatically created in path :"/home/denali/Desktop/sd-card/log/*.log". In row[index], index represent column to be extracted. @param message_ack - (bool) 'True' - if ack is satisfied in log / 'False' - if ack condition is not satisfied @param message_text - (string) message text to be extracted from log. @return content_record - (list) list contains extracted data (ack_req, ack_bak, message, message_id). """ content_record = [] file_name = get_extracted_file() if message_text != None: message = get_message_from_log(file_name, message_text) content_record.append(message) if message_ack != False: ack_req_status, ack_req_value, message_id = get_ack_request_details(file_name, message_text) ack_bak_value = ack_req_value.replace(":-", ":") # getting negative requested ack from positive requested ack content_record.append(ack_req_status) content_record.append(message_id.lower()) if message_ack != False and ack_bak_value != None: ack_bak_status = get_bak_request_details(file_name, ack_bak_value) content_record.append(ack_bak_status) return content_record