def main(self, argv=None): global tmp_dir logger.debug('Command arguments: %s' % self.args) cleanup.init() Iris.fix_terminal_encoding() tmp_dir = self.__create_tempdir() # Create workdir (usually ~/.iris, used for caching etc.) # Assumes that no previous code will write to it. if not os.path.exists(self.args.workdir): logger.debug('Creating working directory %s' % self.args.workdir) os.makedirs(self.args.workdir) if self.args.firefox == 'local': # Use default Firefox installation logger.info('Running with default installed Firefox build') if Settings.getOS() == Platform.MAC: self.fx_app = self.get_test_candidate('/Applications/Firefox.app/Contents') elif Settings.getOS() == Platform.WINDOWS: if os.path.exists('C:\\Program Files (x86)\\Mozilla Firefox'): self.fx_app = self.get_test_candidate('C:\\Program Files (x86)\\Mozilla Firefox') else: self.fx_app = self.get_test_candidate('C:\\Program Files\\Mozilla Firefox') else: self.fx_app = self.get_test_candidate('/usr/lib/firefox') else: self.fx_app = self.get_test_candidate(self.args.firefox) self.fx_path = self.fx_app.exe self.version = self.fx_app.version self.build_id = self.fx_app.build_id return 0
def init_tesseract_path(self): which_tesseract = \ subprocess.Popen('which tesseract', stdout=subprocess.PIPE, shell=True).communicate()[0].rstrip() path_not_found = False current_os = Settings.get_os() if current_os == Platform.WINDOWS: win_default_tesseract_path = 'C:\\Program Files (x86)\\Tesseract-OCR' if '/c/' in str(which_tesseract): win_which_tesseract_path = which_tesseract.replace('/c/', 'C:\\').replace('/', '\\') + '.exe' else: win_which_tesseract_path = which_tesseract.replace('\\', '\\\\') if self.check_tesseract_path(win_default_tesseract_path): pytesseract.pytesseract.tesseract_cmd = win_default_tesseract_path + '\\tesseract' elif self.check_tesseract_path(win_which_tesseract_path): pytesseract.pytesseract.tesseract_cmd = win_which_tesseract_path else: path_not_found = True elif current_os == Platform.LINUX or current_os == Platform.MAC: if self.check_tesseract_path(which_tesseract): pytesseract.pytesseract.tesseract_cmd = which_tesseract else: path_not_found = True else: path_not_found = True if path_not_found: logger.critical('Unable to find Tesseract.') logger.critical('Please consult wiki for complete setup instructions.') self.finish(1)
def init_tesseract_path(self): win_tesseract_path = 'C:\\Program Files (x86)\\Tesseract-OCR' osx_linux_tesseract_path_1 = '/usr/local/bin/tesseract' osx_linux_tesseract_path_2 = '/usr/bin/tesseract' path_not_found = False current_os = Settings.getOS() if current_os == Platform.WINDOWS: if self.check_tesseract_path(win_tesseract_path): pytesseract.pytesseract.tesseract_cmd = win_tesseract_path + '\\tesseract' else: path_not_found = True elif current_os == Platform.LINUX or current_os == Platform.MAC: if self.check_tesseract_path(osx_linux_tesseract_path_1): pytesseract.pytesseract.tesseract_cmd = osx_linux_tesseract_path_1 elif self.check_tesseract_path(osx_linux_tesseract_path_2): pytesseract.pytesseract.tesseract_cmd = osx_linux_tesseract_path_2 else: path_not_found = True else: path_not_found = True if path_not_found: logger.critical('Unable to find Tesseract.') logger.critical('Please consult wiki for complete setup instructions.') self.finish(1)
def check_keyboard_state(self): is_lock_on = False if Settings.get_os() != Platform.MAC: if Key.is_lock_on(Key.CAPS_LOCK): logger.error('Cannot run Iris because Key.CAPS_LOCK is on. Please turn it off to continue.') is_lock_on = True if Key.is_lock_on(Key.NUM_LOCK): logger.error('Cannot run Iris because Key.NUM_LOCK is on. Please turn it off to continue.') is_lock_on = True if Key.is_lock_on(Key.SCROLL_LOCK): logger.error('Cannot run Iris because Key.SCROLL_LOCK is on. Please turn it off to continue.') is_lock_on = True else: try: cmd = subprocess.Popen('xset q', shell=True, stdout=subprocess.PIPE) except subprocess.CalledProcessError as e: logger.error('Command failed: %s' % repr(e.cmd)) raise Exception('Unable to run command') else: keys = ['Caps', 'Num', 'Scroll'] locked = None for line in cmd.stdout: for key in keys: if key in line: value = ' '.join(line.split()) if key in value[0:len(value) / 3]: button = value[0:len(value) / 3] if "off" in button: is_lock_on = False else: is_lock_on = True locked = key break elif key in value[len(value) / 3:len(value) / 3 + len(value) / 3]: button = value[len(value) / 3:len(value) / 3 + len(value) / 3] if "off" in button: is_lock_on = False else: is_lock_on = True locked = key break else: button = value[len(value) / 3 * 2:len(value)] if "off" in button: is_lock_on = False else: is_lock_on = True locked = key break if is_lock_on: logger.error('Cannot run Iris because Key.%s_LOCK is toggled.' % locked.upper()) logger.error('Please turn it off to continue.') break IrisCore.shutdown_process('Xquartz') if is_lock_on: self.finish(code=1)
def at_exit(): if hasattr(Iris, 'process_list'): logger.debug('There are %s queued process(es) to terminate.' % len(Iris.process_list)) for process in Iris.process_list: logger.debug('Terminating process.') process.terminate() process.join() if Settings.is_mac(): # Extra call to shutdown the program we use to check keyboard lock, # in case Iris was terminated abruptly. IrisCore.shutdown_process('Xquartz')
def initialize_platform(self): self.args = parse_args() self.module_dir = IrisCore.get_module_dir() self.platform = get_platform() self.os = Settings.get_os() self.create_working_directory() self.create_run_directory() initialize_logger(LOG_FILENAME, self.args.level) IrisCore.create_profile_cache() Iris.process_list = [] self.local_web_root = os.path.join(self.module_dir, 'iris', 'local_web') self.base_local_web_url = 'http://127.0.0.1:%s' % self.args.port self.create_test_json() self.create_arg_json() self.test_list = [] self.test_packages = []
def __init__(self): self.args = parse_args() initialize_logger(LOG_FILENAME, self.args.level) self.process_list = [] self.check_keyboard_state() self.init_tesseract_path() self.check_7zip() self.module_dir = get_module_dir() self.platform = get_platform() self.os = Settings.getOS() self.local_web_root = os.path.join(self.module_dir, 'iris', 'local_web') self.base_local_web_url = 'http://127.0.0.1:%s' % self.args.port self.start_local_web_server(self.local_web_root, self.args.port) self.main() self.create_run_directory() run(self)
def get_test_candidate(self): """Download and extract a build candidate. Build may either refer to a Firefox release identifier, package, or build directory. :param: build: str with firefox build :return: Installation path for the Firefox App """ location = '' candidate_app = '' if self.args.firefox == 'local': if Settings.is_mac(): location = '/Applications/Firefox.app/Contents/' candidate_app = os.path.join(location, 'MacOS', 'firefox') elif Settings.is_windows(): location = 'C:\\Program Files (x86)\\Mozilla Firefox' if not os.path.exists(location): location = 'C:\\Program Files\\Mozilla Firefox' candidate_app = os.path.join(location, 'firefox.exe') elif Settings.is_linux(): location = '/usr/lib/firefox' candidate_app = os.path.join(location, 'firefox') else: logger.critical('Platform not supported') self.finish(code=5) if not os.path.isdir(location): logger.critical( 'Firefox not found. Please download if from https://www.mozilla.org/en-US/firefox/new/' ) self.finish(code=5) return candidate_app else: try: locale = 'ja-JP-mac' if self.args.locale == 'ja' and Settings.is_mac( ) else self.args.locale type, scraper_details = get_scraper_details( self.args.firefox, Settings.CHANNELS, os.path.join(IrisCore.get_working_dir(), 'cache'), locale) scraper = FactoryScraper(type, **scraper_details) firefox_dmg = scraper.download() install_folder = install(src=firefox_dmg, dest=IrisCore.get_current_run_dir()) binary = get_binary(install_folder, 'Firefox') channel = get_firefox_channel(binary) latest_type, latest_scraper_details = get_latest_scraper_details( channel) latest_path = FactoryScraper(latest_type, **latest_scraper_details).filename self.latest_version = get_version_from_path(latest_path) logger.info('Latest available version for %s channel is: %s' % (channel, self.latest_version)) return binary except errors.NotFoundError: logger.critical( 'Specified build (%s) has not been found. Closing Iris ...' % self.args.firefox) self.finish(5)
def control_center(self): # If user provides custom command-line arguments, we will skip the control center. if len(sys.argv) > 1 and not self.args.control: return True else: # Copy web assets to working directory. dir_util.copy_tree( os.path.join(self.module_dir, 'iris', 'cc_files'), self.args.workdir) # Copy profile for Firefox. profile_path = os.path.join(self.args.workdir, 'cc_profile') if os.path.exists(profile_path): shutil.rmtree(profile_path) Profile._get_staged_profile(Profile.LIKE_NEW, profile_path) # Open local installation of Firefox. paths = [] is_installed = False fx_path = '' if Settings.get_os() == Platform.MAC: paths.append( '/Applications/Firefox.app/Contents/MacOS/firefox') paths.append( '/Applications/Firefox Developer Edition.app/Contents/MacOS/firefox' ) paths.append( '/Applications/Firefox Nightly.app/Contents/MacOS/firefox') elif Settings.get_os() == Platform.WINDOWS: paths.append( 'C:\\Program Files (x86)\\Mozilla Firefox\\firefox.exe') paths.append( 'C:\\Program Files (x86)\\Firefox Developer Edition\\firefox.exe' ) paths.append('C:\\Program Files (x86)\\Nightly\\firefox.exe') paths.append('C:\\Program Files\\Mozilla Firefox\\firefox.exe') paths.append( 'C:\\Program Files\\Firefox Developer Edition\\firefox.exe' ) paths.append('C:\\Program Files\\Nightly\\firefox.exe') else: paths.append('/usr/bin/firefox') paths.append('/usr/lib/firefox/firefox') for path in paths: if os.path.exists(path): fx_path = path is_installed = True break if not is_installed: logger.error( 'Can\'t find local Firefox installation, aborting Iris run.' ) self.finish(1) fx_runner = launch_firefox(fx_path, profile=profile_path, url=self.base_local_web_url) fx_runner.start() server = LocalWebServer(self.args.workdir, self.args.port) # Iris waits for the user to make a choice in the control center. Once they # make a decision, Firefox will quit. quit_firefox() # Check the result of the user's decision. If they have chosen to run tests, # we will continue. Otherwise, abort the current run. if server.result == 'cancel': # We will quit Iris gracefully and clean up. logger.info('Canceling Iris run.') return False else: # We will parse this returned value and turn it into runtime data. logger.debug('Received data from control center: %s' % server.result) # Update app args with new values self.args.locale = server.result['locale'] self.args.firefox = server.result['firefox'] self.args.override = server.result['override'] self.args.port = int(server.result['port']) self.args.email = server.result['email'] self.args.highlight = server.result['highlight'] self.args.mouse = float(server.result['mouse']) self.args.report = server.result['report'] self.args.save = server.result['save'] # For other parts of Iris that get their arguments from parse_args, # we have to update the values there as well. get_global_args().locale = self.args.locale get_global_args().firefox = self.args.firefox get_global_args().override = self.args.override get_global_args().port = self.args.port get_global_args().email = self.args.email get_global_args().highlight = server.result['highlight'] get_global_args().mouse = self.args.mouse get_global_args().report = self.args.report get_global_args().save = self.args.save # Update this URL, used by test cases. self.base_local_web_url = 'http://127.0.0.1:%s' % self.args.port # Parse tests. tests = sorted(server.result['tests']) if len(tests): for package in tests: self.test_packages.append(package) for test in server.result['tests'][package]: self.test_list.append(test['name']) else: logger.info('No tests selected, canceling Iris run.') return False return True
def get_test_candidate(self, build): """Download and extract a build candidate. Build may either refer to a Firefox release identifier, package, or build directory. :param: build: str with firefox build :return: FirefoxApp object for test candidate """ if os.path.isdir(build): candidate_app = fa.FirefoxApp(build, Settings.getOS(), False) return candidate_app else: platform = fd.FirefoxDownloader.detect_platform() if platform is None: logger.error('Unsupported platform: "%s"' % sys.platform) sys.exit(5) # `build` may refer to a build reference as defined in FirefoxDownloader, # a local Firefox package as produced by `mach build`, or a local build tree. if build in fd.FirefoxDownloader.build_urls: # Download test candidate by Firefox release ID logger.info('Downloading Firefox "%s" build for platform "%s"' % (build, platform)) fdl = fd.FirefoxDownloader(self.args.workdir, cache_timeout=1 * 60 * 60) build_archive_file = fdl.download(build, self.args.locale, platform) if build_archive_file is None: self.finish(code=-1) # Extract candidate archive candidate_app = fe.extract(build_archive_file, Settings.getOS(), self.args.workdir, cache_timeout=1 * 60 * 60) candidate_app.package_origin = fdl.get_download_url(build, platform) elif os.path.isfile(build): # Extract firefox build from archive logger.info('Using file "%s" as Firefox package' % build) candidate_app = fe.extract(build, Settings.getOS(), self.args.workdir, cache_timeout=1 * 60 * 60) candidate_app.package_origin = build logger.debug('Build candidate executable is "%s"' % candidate_app.exe) elif os.path.isfile(os.path.join(build, 'mach')): logger.info('Using Firefox build tree at `%s`' % build) dist_globs = sorted(glob.glob(os.path.join(build, 'obj-*', 'dist'))) if len(dist_globs) == 0: logger.critical('"%s" looks like a Firefox build directory, but can\'t find a build in it' % build) self.finish(code=5) logger.debug('Potential globs for dist directory: %s' % dist_globs) dist_dir = dist_globs[-1] logger.info('Using "%s" as build distribution directory' % dist_dir) if 'apple-darwin' in dist_dir.split('/')[-2]: # There is a special case for OS X dist directories: # FirefoxApp expects OS X .dmg packages to contain the .app folder inside # another directory. However, that directory isn't there in build trees, # thus we need to point to the parent for constructing the app. logger.info('Looks like this is an OS X build tree') candidate_app = fa.FirefoxApp(os.path.abspath(os.path.dirname(dist_dir)), Settings.getOS(), True) candidate_app.package_origin = os.path.abspath(build) else: candidate_app = fa.FirefoxApp(os.path.abspath(dist_dir), Settings.getOS(), True) candidate_app.package_origin = os.path.abspath(build) else: logger.critical('"%s" specifies neither a Firefox release, package file, or build directory' % build) logger.critical('Valid Firefox release identifiers are: %s' % ', '.join(fd.FirefoxDownloader.list()[0])) self.finish(5) logger.debug('Build candidate executable is "%s"' % candidate_app.exe) if candidate_app.platform != platform: logger.warning('Platform mismatch detected') logger.critical('Running a Firefox binary for "%s" on a "%s" platform will probably fail' % (candidate_app.platform, platform)) return candidate_app