def create(folder): if not os.path.exists(folder): Log.debug("Create folder: " + folder) try: os.makedirs(folder) except OSError: raise
def wait_for_log(log_file, string_list, not_existing_string_list=None, timeout=60, check_interval=3): """ Wait until log file contains list of string. :param log_file: Path to log file. :param string_list: List of strings. :param not_existing_string_list: List of string that should not be in logs. :param timeout: Timeout. :param check_interval: Check interval. """ end_time = time.time() + timeout all_items_found = False not_found_list = [] log = "" verified_flag = '[VERIFIED]' while time.time() < end_time: not_found_list = [] log = File.read(log_file) # Extract the part of the log that hasn't been previously verified if verified_flag in log: log = File.extract_part_of_text(log, verified_flag) for item in string_list: if item in log: Log.info("'{0}' found.".format(item)) else: not_found_list.append(item) string_list = not_found_list if not not_found_list: all_items_found = True Log.info("All items found") break else: Log.debug("'{0}' NOT found. Wait...".format(not_found_list)) time.sleep(check_interval) if 'BUILD FAILED' in log: Log.error('BUILD FAILED. No need to wait more time!') break if 'Unable to sync files' in log: Log.error('Sync process failed. No need to wait more time!') break if 'errors were thrown' in log: Log.error('Multiple errors were thrown. No need to wait more time!') break # Mark that part of the log as verified by appending a flag at the end. # The second time we read the file we will verify only the text after that flag if Settings.HOST_OS != OSType.WINDOWS: File.append(log_file, verified_flag) if all_items_found: if not_existing_string_list is None: pass else: for item in not_existing_string_list: assert item not in log, "{0} found! It should not be in logs.\nLog:\n{1}".format(item, log) else: Log.info("NOT FOUND: {0}".format(not_found_list)) Log.info('##### ACTUAL LOG #####\n') Log.info(log) Log.info('######################\n') assert False, "Output does not contain {0}".format(not_found_list)
def delete(path, backup_files=False): if os.path.isfile(path): if backup_files: File.__back_up_files(path) os.remove(path) Log.debug('Delete {0}'.format(path)) else: Log.debug('Error: %s file not found' % path)
def unzip(file_path, dest_dir, clean_dest_dir=True): if clean_dest_dir: Folder.clean(dest_dir) Folder.create(dest_dir) try: zfile = zipfile.ZipFile(file_path, 'r') zfile.extractall(dest_dir) zfile.close() except Exception: Log.debug('Failed to unzip file {0}'.format(file_path))
def get_log_file(device_id): command = 'spawn {0} log stream --level=debug'.format(device_id) Process.kill_by_commandline(command) log_file = Simctl.run_simctl_command(command=command, wait=False).log_file if File.exists(log_file): Log.debug('Log of {0} redirected to {1}'.format(device_id, log_file)) return log_file else: message = 'Failed to get logs of {0}'.format(device_id) Log.error(message) raise Exception(message)
def kill_by_handle(file_path): for proc in psutil.process_iter(): try: for item in proc.open_files(): if file_path in item.path: Log.debug("{0} is locked by {1}".format( file_path, proc.name())) Log.debug("Proc cmd: {0}".format(proc.cmdline())) proc.kill() except Exception: continue
def get_log(self): """ Get device log. """ if self.type is DeviceType.EMU or self.type is DeviceType.ANDROID: return Adb.get_logcat(self.id) elif self.type is DeviceType.SIM: Log.debug('Read log file: {0}'.format(self.device_log_file)) return File.read(self.device_log_file) else: raise NotImplementedError('Click not implemented for iOS devices.')
def kill_by_port(port): for proc in psutil.process_iter(): try: connections = proc.connections(kind='inet') if connections: for connection in connections: if connection.laddr.port == port: cmd = ''.join(proc.cmdline()) proc.kill() Log.info( 'Kill processes listening on port {0}.'.format( str(port))) Log.debug('Kill process: ' + cmd) except Exception: pass
def find_by_extension(folder, extension): """ Find by file extension recursively. :param folder: Base folder where search is done. :param extension: File extension. :return: List of found files. """ matches = [] if '.' not in extension: extension = '.' + extension for root, dirs, files in os.walk(folder): for f in files: if f.endswith(extension): Log.debug('File with {0} extension found: {1}'.format(extension, os.path.abspath(f))) matches.append(os.path.join(root, f)) return matches
def get_ids(include_emulators=False): """ Get IDs of available android devices. """ devices = [] output = Adb.run_adb_command('devices -l').output # Example output: # emulator-5554 device product:sdk_x86 model:Android_SDK_built_for_x86 device:generic_x86 # HT46BWM02644 device usb:336592896X product:m8_google model:HTC_One_M8 device:htc_m8 for line in output.splitlines(): if 'model' in line and ' device ' in line: device_id = line.split(' ')[0] if 'emulator' in line and not include_emulators: Log.debug('{0} not included in android device list.'.format(device_id)) else: devices.append(device_id) return devices
def start(simulator_info): # Start iOS Simulator Log.info('Booting {0} ...'.format(simulator_info.name)) simulator_info = Simctl.start(simulator_info=simulator_info) # Start GUI if Process.get_proc_by_commandline('Simulator.app') is not None: Log.debug('Simulator GUI is already running.') else: Log.info('Start simulator GUI.') run(cmd='open -a Simulator') # Return result device = Device(id=simulator_info.id, name=simulator_info.name, type=DeviceType.SIM, version=simulator_info.sdk) TestContext.STARTED_DEVICES.append(device) return device
def replace(path, old_string, new_string, fail_safe=False, backup_files=False): if backup_files: File.__back_up_files(path) content = File.read(path=path) old_text_exists = old_string in content if not fail_safe: assert old_text_exists, 'Can not find "{0}" in {1}'.format(old_string, path) if old_text_exists: new_content = content.replace(old_string, new_string) File.write(path=path, text=new_content) Log.info("") Log.info("##### REPLACE FILE CONTENT #####") Log.info("File: {0}".format(path)) Log.info("Old String: {0}".format(old_string)) Log.info("New String: {0}".format(new_string)) Log.info("") else: Log.debug('Skip replace. Text "{0}" do not exists in {1}.'.format(old_string, path))
def is_text_visible(self, text, case_sensitive=False): is_visible = False if self.type is DeviceType.EMU or self.type is DeviceType.ANDROID: is_visible = Adb.is_text_visible(device_id=self.id, text=text, case_sensitive=case_sensitive) if self.type is DeviceType.SIM: is_visible = SimAuto.is_text_visible(self, text) # Retry find with ORC (only for IOS, for example if macOS automation fails) if not is_visible and (self.type is DeviceType.SIM or self.type is DeviceType.IOS): actual_text = self.get_text() if text in actual_text: is_visible = True else: Log.debug('Current text on {0}: {1}{2}'.format( self.id, os.linesep, actual_text)) return is_visible
def clean(folder): if Folder.exists(folder=folder): Log.debug("Clean folder: " + folder) try: shutil.rmtree(folder) except OSError as error: try: for root, dirs, files in os.walk(folder, topdown=False): for name in files: filename = os.path.join(root, name) if Settings.HOST_OS != OSType.WINDOWS: os.chmod(filename, stat.S_IWUSR) os.remove(filename) for name in dirs: os.rmdir(os.path.join(root, name)) os.rmdir(folder) Log.error('Error: %s - %s.' % (error.filename, error.strerror)) except Exception: Log.info('Kill processes with handle to ' + folder) Process.kill_by_handle(folder) os.system('rm -rf {0}'.format(folder))
def wait_for_text(text, timeout=60): """ Wait for text to be visible screen of host machine. :param text: Text that should be visible on the screen. :param timeout: Timeout in seconds. :return: True if text found, False if not found. """ t_end = time.time() + timeout found = False actual_text = '' while time.time() < t_end: actual_text = Screen.get_screen_text() if text in actual_text: Log.info('"{0}" found on screen.'.format(text)) found = True break else: Log.debug('"{0}" NOT found on screen.'.format(text)) time.sleep(5) if not found: Log.info('Actual text: {0}{1}'.format(os.linesep, actual_text)) return found
def run(cmd, cwd=Settings.TEST_RUN_HOME, wait=True, timeout=600, fail_safe=False, register=True, log_level=logging.DEBUG): # Init result values time_string = datetime.now().strftime('%Y_%m_%d_%H_%M_%S_%f') log_file = os.path.join(Settings.TEST_OUT_LOGS, 'command_{0}.txt'.format(time_string)) complete = False duration = None output = '' # Ensure logs folder exists dir_path = os.path.dirname(os.path.realpath(log_file)) Folder.create(dir_path) # Command settings if not wait: # Redirect output to file File.write(path=log_file, text=cmd + os.linesep + '====>' + os.linesep) cmd = cmd + ' >> ' + log_file + ' 2>&1 &' # Log command that will be executed: Log.log(level=log_level, msg='Execute command: ' + cmd) Log.log(level=logging.DEBUG, msg='CWD: ' + cwd) # Execute command: if wait: start = time.time() with open(log_file, mode='w') as log: if Settings.HOST_OS == OSType.WINDOWS: process = subprocess.Popen(cmd, cwd=cwd, shell=True, stdout=log, stderr=log) else: process = subprocess.Popen(cmd, cwd=cwd, shell=True, stdout=subprocess.PIPE, stderr=log) # Wait until command complete try: process.wait(timeout=timeout) complete = True out, err = process.communicate() if out is not None: if Settings.PYTHON_VERSION < 3: output = str(out.decode('utf8').encode('utf8')).strip() else: output = out.decode("utf-8").strip() except subprocess.TimeoutExpired: process.kill() if fail_safe: Log.error('Command "{0}" timeout after {1} seconds.'.format( cmd, timeout)) else: raise # Append stderr to output stderr = File.read(path=log_file) if stderr: output = output + os.linesep + File.read(path=log_file) # noinspection PyBroadException try: File.delete(path=log_file) except Exception: Log.debug('Failed to clean log file: {0}'.format(log_file)) log_file = None end = time.time() duration = end - start else: process = psutil.Popen(cmd, cwd=cwd, shell=True, stdin=None, stdout=None, stderr=None, close_fds=True) # Get result pid = process.pid exit_code = process.returncode # Log output of the process if wait: Log.log(level=log_level, msg='OUTPUT: ' + os.linesep + output + os.linesep) else: Log.log(level=log_level, msg='OUTPUT REDIRECTED: ' + log_file + os.linesep) # Construct result result = ProcessInfo(cmd=cmd, pid=pid, exit_code=exit_code, output=output, log_file=log_file, complete=complete, duration=duration) # Register in TestContext if psutil.pid_exists(result.pid) and register: TestContext.STARTED_PROCESSES.append(result) # Return the result return result
def unpack_tar(file_path, dest_dir): try: tar_file = tarfile.open(file_path, 'r:gz') tar_file.extractall(dest_dir) except Exception: Log.debug('Failed to unpack .tar file {0}'.format(file_path))