def _exec(self, cmd, timeout=None, force_execution=False, wait_for_response=True): """ Internal method that execute std command on device :type cmd: str :param cmd: cmd to be executed :type timeout: integer :param timeout: Script execution timeout in ms :type force_execution: Boolean :param force_execution: Force execution of command without check phone connected (dangerous) :type wait_for_response: Boolean :param wait_for_response: Wait response from adb before statuing on command :return: output str :rtype: string """ silent_mode = False if timeout is None: timeout = self._uecmd_default_timeout # (result, output) = self._device.run_cmd(cmd, timeout, force_execution, wait_for_response) if wait_for_response: return_code, output = internal_shell_exec(cmd=cmd, timeout=timeout, silent_mode=silent_mode) else: # Async operation is going to be started, we cannot provide a return_code # Return SUCCESS by default return_code = Global.SUCCESS output = "" run_local_command(args=cmd, get_stdout=not silent_mode) if return_code == Global.SUCCESS: if output is not None: return output else: raise DeviceException(DeviceException.PHONE_OUTPUT_ERROR, "\"" + cmd + "\" returned null output !") else: raise DeviceException(DeviceException.PHONE_OUTPUT_ERROR, output)
def _run(self): """ Execute command line """ self._proc = None return_code = None error_message = "" try: cmd = self._get_cmd() if self._logger: self._logger.debug("Execute: {0} (uid:{1})".format( cmd, os.getuid())) self._proc, q = run_local_command(cmd) timeout = float(self._timeout) while timeout > 0 and self._proc is not None and self._proc.poll( ) is None: # pylint: disable=C0103 # Agree to keep t0 & t1 variable names t0 = time.time() time.sleep(0.2) t1 = time.time() timeout -= (t1 - t0) stdout_data_list = self._dequeue(q) self._analyze_output(stdout_data_list) if timeout <= 0: # Timeout terminated error_message = "CmdExecManager: Timeout while command execution (%s)!" % cmd else: # Process terminated # Get return code if self._proc is not None: return_code = self._proc.poll() # assume that return code of application is UNIX # so valid range is 0-255 # check that return code is valid if return_code > 255 or return_code < 0: # consider return code as invalid return_code = None # Execution ends without exception if return_code is None: error_message = "CmdExecManager: unexpected error with thread execution (cmd= %s )" % cmd except Exception as ex: # pylint: disable=W0703 error_message = "CmdExecManager: unexpected exception with thread execution (cmd= %s), error= %s" % ( cmd, str(ex)) finally: self._stop() if self._logger: self._logger.debug( "CmdExecManager: execution terminated (return_code=%s, error_message=%s)" % (str(return_code), error_message)) # Return ouput datas return return_code, error_message
def delete_route(self, net_ip_addr): """ Delete an IP route :type net_ip_addr: str :param net_ip_addr: IP address of the route :rtype: str :return: The command return """ # Check OS platform os_str = platform.system().upper() if os_str == 'LINUX': # Linux: msg = "get_net_info_list: Not implemented for Linux platform" raise AcsBaseException(AcsBaseException.FEATURE_NOT_IMPLEMENTED, msg) # Prepare command args = shlex.split("route DELETE %s" % net_ip_addr) try: # Debug log msg = "route DELETE %s" % net_ip_addr self.get_logger().debug(msg) p, q = run_local_command(args, False) data = p.communicate() # Use code page 860 to convert read bytes from windows console, # then normalize chars and convert them to utf-8 (ignore unknown symbols) strdata = unicodedata.normalize('NFKD', data[0].decode('cp860')).encode( 'ascii', 'ignore') return strdata except Exception as error: msg = "delete_route: %s" % str(error) raise AcsBaseException(AcsBaseException.OPERATION_FAILED, msg)
def get_interface_from_list(self, if_name): """ Parse Window command: "route print" return, and return searched Interface :type if_name: String :param if_name: name of the interface to search :rtype: dict :return: if_list is a of dict(if_number,mac_address) """ # Check OS platform os_str = platform.system().upper() if os_str == 'LINUX': # Linux: msg = "get_interface_list: Not implemented for Linux platform" raise AcsBaseException(AcsBaseException.FEATURE_NOT_IMPLEMENTED, msg) # Prepare command args = shlex.split("route print") try: p, q = run_local_command(args, False) data = p.communicate() # Use code page 860 to convert read bytes from windows console, # then normalize chars and convert them to utf-8 (ignore unknown symbols) strdata = unicodedata.normalize('NFKD', data[0].decode('cp860')).encode( 'ascii', 'ignore') # Parse following str data to extract IF numbers and its MAC addresses (ex: out_tupple=(13,9c-8e-99-dd-d5-97)) # "===========================================================================\n" # "Interface List\n" # " 13...9c 8e 99 dd d5 97 ......Intel(R) 82579LM Gigabit Network Connection\n" if_strdata = [ elem.strip(" ") for elem in strdata.split( "===========================================================================" )[1].split("\n") if match("^[0-9]", elem.strip(" ")) ] if_list = {} for line in if_strdata: data = [str(elem.strip(" ")) for elem in line.split("...")][:2] # Stop parsing when get " 1..........." if data[1] != "": if if_name in line: if_list[data[0]] = data[1].replace(" ", "-").upper() else: break # Debug msg = "Interface found: %s" % str(if_list) self.get_logger().debug(msg) return if_list except Exception as error: msg = "get_interface_from_list: %s" % str(error) raise AcsBaseException(AcsBaseException.OPERATION_FAILED, msg)
def add_route(self, net_ip_addr, ip_mask, gateway_ip_addr, if_number): """ Add an IP route. :type net_ip_addr: str :param net_ip_addr: IP address of the route :type ip_mask: str :param ip_mask: IP Mask of the route (ex: "255.255.255.0") :type gateway_ip_addr: str :param gateway_ip_addr: IP address of the Gateway :type if_number: str :param if_number: Network Interface number of the Gateway (ex: "17") :rtype: str :return: The command return """ # Check OS platform os_str = platform.system().upper() if os_str == 'LINUX': # Linux: msg = "get_net_info_list: Not implemented for Linux platform" raise AcsBaseException(AcsBaseException.FEATURE_NOT_IMPLEMENTED, msg) # Prepare command args = shlex.split("route ADD %s MASK %s %s IF %s" % (net_ip_addr, ip_mask, gateway_ip_addr, if_number)) try: # Debug log msg = "route ADD %s MASK %s %s IF %s" \ % (net_ip_addr, ip_mask, gateway_ip_addr, if_number) self.get_logger().debug(msg) p, q = run_local_command(args, False) data = p.communicate() # Use code page 860 to convert read bytes from windows console, # then normalize chars and convert them to utf-8 (ignore unknown symbols) strdata = unicodedata.normalize('NFKD', data[0].decode('cp860')).encode( 'ascii', 'ignore') return strdata except Exception as error: msg = "add_route: %s" % str(error) raise AcsBaseException(AcsBaseException.OPERATION_FAILED, msg)
def __start_logcat_thread(self): cmd = self._device.format_cmd(self._logcat_cmd_line, True) self._adb_process, self._adb_stdout = run_local_command(cmd) return self._adb_process and self._adb_stdout
def send(self, media, sender_number, destination_number, subject, text, attachment_file): """ Prepare and send MT MMS from NowSMSServer This MT MMS is send by NowSMSServer to the DUT: 1- Local computer use JAVA with a sendmms.jar file to request the SMS server a MMS sending (via server API), using NowSMSServer credential from "SMS Users" account: $ java sendmms.jar "http://10.102.161.47:8800" "telephony" "telephony" "8960" "0123456789" "MMS subject" "This is my MMS text" "ACS_Sample_Picture.jpg" 2- sendmms.jar application will return ok message and mms id if MMS creation success: "Response Code ->OK" "MMSMessageID=20131213/15/06096742" 3- In NowSMSServer SMSC HTTP connection settings for Agilent 8960, URL text and binary templates must be set as following: /sms/send/?PhoneNumber=@@PhoneNumber@@&TEXT=@@Text@@&SENDER=@@Sender@@ /sms/send/?PhoneNumber=@@PhoneNumber@@&DATA=@@Data@@&UDH=@@UDH@@&PID=@@PIDdecimal@@&DCS=@@DCSdecimal@@&SENDER=@@Sender@@ Routing is also add for phone number use in destination of MT MMS (ex: 0123456789) 4- Finally on the DUT connected to the Agilent 8960 equipment, apn (apn=MMS, type=default,mms) must be set accordingly to NowSMSServer MMSC, with MMSC users credential and MMSC URL set like this: "http://mmsc_url_IP:port/login=password" The sendmms.java file could be download from: http://www.nowsms.com/doc/submitting-mms-messages/send-mms-message-with-java :type media : str :param media : Type of the media to be sent (picture, audio, video, text) :type sender_number : str :param sender_number : Phone number of the sender (MT MMS, sender is NowSMSServer) :type destination_number : str :param destination_number : Phone number of the recipient (DUT) :type subject : str :param subject : Subject of the MMS :type text : str :param text : Text of the MMS :type attachment_file : str :param attachment_file : File to be put in attachment in the MMS """ regex_search = None strdata = "" attaches = attachment_file.split(";") self._logger.debug(len(attaches)) # Check media parameter media_type = ["picture", "audio", "video", "text"] if media not in media_type: msg = "[NOWSMS_SERVER] Media type incorrect: %s (instead %s)" % ( str(media), str(media_type)) raise AcsBaseException(AcsBaseException.INVALID_PARAMETER, msg) for attach in attaches: mms_attached_file = attach # Call the sendmms.jar to send mms jar_file_path = \ os.path.normpath(os.path.join(os.getcwd(), "..", "..", "acs_test_scripts", "Lib", "sendmms.jar")) cmd = [ "java", "-jar", jar_file_path, self._url, self._user, self._password, sender_number, destination_number, subject, text, mms_attached_file ] try: # Debug log self._logger.debug( "[NOWSMS_SERVER] MT MMS is going to be sent using following JAVA cmd : %s" % str(cmd)) p, q = run_local_command(cmd, False) data = p.communicate() strdata = data[0].decode() # Debug log self._logger.debug("[NOWSMS_SERVER] JAR output:'%s'" % strdata) # Extract Response Code and MMSMessageID cmd_result = strdata.replace("\r", " ").replace("\n", " ") regex_search = re.search( "^.*Response Code.*>(\S*).*MMSMessageID=(\S*).*$", cmd_result) if regex_search is not None: response_code = str(regex_search.group(1)) mms_message_id = str(regex_search.group(2)) # Debug log self._logger.debug( "[NOWSMS_SERVER] MT MMS, Response Code = '%s'" % response_code) self._logger.debug( "[NOWSMS_SERVER] MT MMS, MMSMessageID = '%s'" % mms_message_id) else: msg = "Unable to found response code." raise AcsBaseException(AcsBaseException.OPERATION_FAILED, msg) except Exception as error: msg = "[NOWSMS_SERVER] Exception: %s" % str(error) raise AcsBaseException(AcsBaseException.OPERATION_FAILED, msg) # Check result of the operation if response_code != "OK" or mms_message_id == "": msg = "[NOWSMS_SERVER] ERROR: " + strdata self._logger.error(msg) raise AcsBaseException(AcsBaseException.OPERATION_FAILED, msg) else: self._logger.info( "[NOWSMS_SERVER] MT MMS request sent: MMSMessageID = '%s'" % mms_message_id)
def get_net_info_list(self): """ Parse Window command: "ipconfig /all" return, and return a list of Network connection informations :rtype: list :return: net_connection_list is a list of dict(network_attribute, values) """ # Check OS platform os_str = platform.system().upper() if os_str == 'LINUX': # Linux: msg = "get_net_info_list: Not implemented for Linux platform" raise AcsBaseException(AcsBaseException.FEATURE_NOT_IMPLEMENTED, msg) # Prepare command args = shlex.split("ipconfig /all") try: p, q = run_local_command(args, False) output = "" # Poll command q during 5 seconds to get all command std_out if q is not None: start = time.time() while time.time() < start + 5: try: line = q.get(timeout=5) except Empty: break output += line data = p.communicate() # Use code page 860 to convert read bytes from windows console, # then normalize chars and convert them to utf-8 (ignore unknown symbols) strdata = unicodedata.normalize('NFKD', data[0].decode('cp860')).encode( 'ascii', 'ignore') strdata += output mac_strdata = [ str(elem.strip(" ")) for elem in strdata.split("\n") ] # Init variables net_connection_list = [] net_connection = {} # Process each line for i in mac_strdata: # Empty line if i == "": pass # New network connection (""blabla:") or new connection param ("blabla :") elif ":" in i: entry = i.split(":") if entry[1] == "": # New connection if entry[0][-1] != " ": net_connection_list.append(net_connection) net_connection = {} # New "empty" param in current network connection else: net_connection[entry[0].split(".") [0].strip()] = entry[1].strip() # New param in current network connection else: net_connection[entry[0].split(".") [0].strip()] = entry[1].strip() # Save last Net connection entries net_connection_list.append(net_connection) # Return the list of connection info return net_connection_list except Exception as error: msg = "get_net_info_list: %s" % str(error) raise AcsBaseException(AcsBaseException.OPERATION_FAILED, msg)
def run(self, context): """ Runs the test step :type context: TestStepContext :param context: test case context """ DeviceTestStepBase.run(self, context) self.__json = [] self.__mutex = Lock() # ------------------------- get params ---------------------------- droidbot_jar_path = context.get_info("JAR_FILE_PATH_DROIDBOT") pnptests_jar_path = context.get_info("JAR_FILE_PATH_PNP_TESTS") droidbot_extra_args = self._pars.extra_opts self._droidbot_test_name = self._pars.test_name self.__droidbot_timer = self._pars.timeout self._iteration_name = self._droidbot_test_name.split('.')[-1] # get test case name, based on its path testcase_name = self._testcase_name.replace("\\", "/").split("/")[-1] # add each iteration in external report self._logger.info("RunPnpPerf: Starting") cmd = "adb shell uiautomator runtest {0} {1} -s -c {2}".format( droidbot_jar_path, pnptests_jar_path, self._droidbot_test_name) if droidbot_extra_args: cmd += " " + str(droidbot_extra_args) # ------------------------- run droidbot ---------------------------- self._logger.info("Droidbot cmd: {}".format(cmd)) # Start watchdog for droidbot cancelable = Cancel() min_timeout = 60 logtag = "DROIDBOT_TIMER" self._device.get_device_logger().add_trigger_message(logtag) thread = Thread(target=self.droidbot_watchdog, args=(cancelable, min_timeout, logtag)) thread.start() # run droidbot command, using cancel object from watchdog regex_dict_result = "INSTRUMENTATION_STATUS: result=(?P<dict_result>{.*})" regex_dict_report = "INSTRUMENTATION_STATUS: report=(?P<dict_report>{.*})" _proc, q = run_local_command(cmd) output = "" self.__droidbot_timer *= 60 verdict = Global.FAILURE while self.__droidbot_timer > 0 and _proc is not None and _proc.poll( ) is None: # pylint: disable=C0103 # Agree to keep t0 & t1 variable names t0 = time.time() time.sleep(0.2) t1 = time.time() self.__mutex.acquire() self.__droidbot_timer -= (t1 - t0) self.__mutex.release() stdout_data_list = self._dequeue(q) for el in stdout_data_list: output += el + "\n" self._logger.debug("uiautomator_output : %s" % el) if "report" in el: matches_res = re.compile(regex_dict_report).search(el) if matches_res: content = matches_res.group('dict_report') #FIXME: Need to convert verdict into Global.Status verdict = Global.SUCCESS #if content["verdict"] == "PASS" else elif "result" in el: matches_res = re.compile(regex_dict_result).search(el) content = None if matches_res: content = matches_res.group('dict_result') self._send_iteration(content) # droidbot command is done : call cancel() to stop watchdog cancelable.cancel() if verdict != Global.SUCCESS: raise DeviceException(DeviceException.OPERATION_FAILED, "RunPnpPerf: run_cmd failed") # ------------------------- format output ---------------------------- # json dict is printed in logs with all test output data # example : OK (1 test) # this log will indicate that all tests have been successfully executed regex_result_ok = re.compile("OK \(\d+ test\)") results = [] success = False for line in output.split('\n'): # retrieve test output info matches_res = re.compile(regex_dict_result).search(line) if matches_res: content = matches_res.group('dict_result') try: # serialize string as dict json_test_result = json.loads(content) results.append(json_test_result) except ValueError as error: self._logger.warning( "error during loading {0} : {1}".format( content, error)) elif regex_result_ok.match(line): success = True # ------------------------- analyze output ---------------------------- if results: # get artifacts from device artifacts_dir = os.path.join( self._device.get_report_tree().get_report_path(), self._testcase_name, "{0}_artifacts".format(testcase_name)) if not os.path.exists(artifacts_dir): os.makedirs(artifacts_dir) for result in results: if 'artifacts' in result: for artifact in result['artifacts']: artifact_dir = os.path.join( artifacts_dir, os.path.join(*artifact.split('/')[-3:-1])) if not os.path.exists(artifact_dir): os.makedirs(artifact_dir) adb_command = "adb pull " + artifact + " " + os.path.join( artifact_dir, artifact.split('/')[-1]) self._device.run_cmd(adb_command, 30) # write results in json file # example : _Report/ReportCampaign/PHONE1/test_case_name/results.json test_data_dir = os.path.join( self._device.get_report_tree().get_report_path(), self._testcase_name, "{0}_result".format(testcase_name)) # create folder if it does not exist if not os.path.exists(test_data_dir): os.makedirs(test_data_dir) # dump json to string try: json_string = json.dumps(results) except Exception as e: msg = "Error while dumping json results to string ({0})".format( e) self._logger.error(msg) raise DeviceException(DeviceException.OPERATION_FAILED, "RunPnpPerf: {0}".format(msg)) # dump data in file score_file_path = os.path.join(test_data_dir, "results.json") with open(score_file_path, 'w') as outfile: outfile.write(json_string) # compute scores and add them to secondary report success = success and self.computeScores( context, self._device, testcase_name, json_string) else: raise DeviceException( DeviceException.OPERATION_FAILED, "RunPnpPerf: no results returned, test has failed!") if not success: raise DeviceException( DeviceException.OPERATION_FAILED, "RunPnpPerf: check logs, test has not been executed properly") self._logger.info("RunPnpPerf: Done")