Пример #1
0
    def _get_test_candidate(version: str, locale: str) -> str or None:
        """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
        """
        logger.debug("Getting build, version %s, locale %s" % (version, locale))
        if version == "local":
            candidate = PathManager.get_local_firefox_path()
            if candidate is None:
                logger.critical("Firefox not found. Please download if from https://www.mozilla.org/en-US/firefox/new/")
            return candidate
        elif os.path.isfile(version):
            return version
        else:
            try:
                s_t, s_d = _get_scraper_details(
                    version, CHANNELS, os.path.join(PathManager.get_working_dir(), "cache"), locale
                )

                scraper = FactoryScraper(s_t, **s_d)
                firefox_dmg = scraper.download()

                install_dir = install(
                    src=firefox_dmg,
                    dest=os.path.join(
                        PathManager.get_temp_dir(), "firefox{}{}".format(normalize_str(version), normalize_str(locale))
                    ),
                )

                return get_binary(install_dir, "Firefox")
            except errors.NotFoundError:
                logger.critical("Specified build {} has not been found. Closing Iris ...".format(version))
        return None
Пример #2
0
def get_test_params():
    tests_to_execute = collect_tests()
    pytest_args = []
    if get_core_args().rerun:
        failed_tests_file = os.path.join(PathManager.get_working_dir(), "lastfail.txt")
        tests_dir = os.path.join(PathManager.get_tests_dir(), get_core_args().target)
        failed_tests = []
        with open(failed_tests_file, "r") as f:
            for line in f:
                failed_tests.append(line.rstrip("\n"))
        f.close()
        # Read first line to see if these tests apply to current target.
        if tests_dir in failed_tests[0]:
            pytest_args = failed_tests
        else:
            logging.error(
                "The -a flag cannot be used now because the last failed tests don't match current target."
            )
    else:
        if len(tests_to_execute) > 0:
            for running in tests_to_execute:
                pytest_args.append(running)
        else:
            exit_iris("No tests to execute.", status=1)
    return pytest_args
Пример #3
0
def check_target(target: str = None):
    """Checks if provided target exists."""
    # Currently not in use, but maintaining for possible future use.

    if target is None:
        logger.warning("No target provided.")

    local_target_path = os.path.join(PathManager.get_module_dir(), "targets")
    package_target_path = os.path.join(PathManager.get_module_dir(), "moziris",
                                       "targets")

    if os.path.exists(os.path.join(local_target_path, target)):
        return True
    if os.path.exists(os.path.join(package_target_path, target)):
        return True

    target_list = []
    local_path_exists = os.path.exists(local_target_path)
    package_path_exists = os.path.exists(package_target_path)

    if local_path_exists:
        target_list += scan_dir(local_target_path)

    if package_path_exists:
        target_list += scan_dir(package_target_path)

    if not local_path_exists and not package_path_exists:
        path_warning(local_target_path)
    else:
        logger.critical("Target %s doesn't exist.")
        logger.critical("Did you mean to choose one of these instead?")
        for target in target_list:
            logger.critical("\t%s" % target)

    return False
Пример #4
0
    def make_profile(profile_type: Profiles = None, preferences: dict = None):
        """Internal-only method used to create profiles on disk.

        :param profile_type: Profiles.BRAND_NEW, Profiles.LIKE_NEW, Profiles.TEN_BOOKMARKS, Profiles.DEFAULT
        :param preferences: A dictionary containing profile preferences
        """
        if profile_type is None:
            profile_type = Profiles.DEFAULT

        if preferences is None:
            if profile_type is Profiles.BRAND_NEW:
                preferences = FirefoxSettings.DEFAULT_FX_PREFS
            else:
                preferences = {}

        test_root = PathManager.get_current_tests_directory()
        current_test = os.environ.get('CURRENT_TEST')
        test_path = current_test.split(test_root)[1].split('.py')[0][1:]
        profile_path = os.path.join(PathManager.get_current_run_dir(),
                                    test_path, 'profile')

        if profile_type is Profiles.BRAND_NEW:
            logger.debug('Creating brand new profile: %s' % profile_path)
        elif profile_type in (Profiles.LIKE_NEW, Profiles.TEN_BOOKMARKS):
            logger.debug('Creating new profile from %s staged profile.' %
                         profile_type.value.upper())
            profile_path = FirefoxProfile._get_staged_profile(
                profile_type, profile_path)
        else:
            raise ValueError('No profile found: %s' % profile_type.value)

        return MozProfile(profile=profile_path, preferences=preferences)
Пример #5
0
def launch_control_center():
    profile_path = os.path.join(PathManager.get_working_dir(), "cc_profile")
    fx_path = PathManager.get_local_firefox_path()
    if fx_path is None:
        logger.error("Can't find local Firefox installation, aborting Iris run.")
        return False, None

    args = ["http://127.0.0.1:%s" % get_core_args().port]
    process_args = {"stream": None}
    profile = MozProfile(profile=profile_path, preferences=get_fx_prefs())
    if OSHelper.is_windows():
        process = subprocess.Popen(
            [
                fx_path,
                "-no-remote",
                "-new-tab",
                args,
                "--wait-for-browser",
                "-foreground",
                "-profile",
                profile.profile,
            ],
            shell=False,
        )

    else:
        fx_runner = FirefoxRunner(
            binary=fx_path, profile=profile, cmdargs=args, process_args=process_args
        )
        fx_runner.start()
    logger.debug("Launching web server for directory %s" % PathManager.get_working_dir())
    server = LocalWebServer(PathManager.get_working_dir(), get_core_args().port)
    server.stop()
    time.sleep(Settings.DEFAULT_UI_DELAY)

    if OSHelper.is_mac():
        type(text="q", modifier=KeyModifier.CMD)
    elif OSHelper.is_windows():
        type(text="w", modifier=[KeyModifier.CTRL, KeyModifier.SHIFT])
    else:
        type(text="q", modifier=KeyModifier.CTRL)
    if OSHelper.is_windows():
        if process.pid is not None:
            try:
                logger.debug("Closing Firefox process ID: %s" % process.pid)
                process = psutil.Process(process.pid)
                for proc in process.children(recursive=True):
                    proc.kill()
                process.kill()
            except psutil.NoSuchProcess:
                pass
    else:
        try:
            fx_runner.stop()
        except Exception as e:
            logger.debug("Error stopping fx_runner")
            logger.debug(e)

    return server.result
Пример #6
0
def collect_tests():
    """Collects tests based on include/exclude criteria and selected target."""
    target = core_args.target
    test_list = []

    include = core_args.test
    exclude = core_args.exclude
    if os.path.isfile(include):
        with open(include, "r") as f:
            for line in f:
                test_list.append(line.rstrip("\n"))
        f.close()
    else:
        tests_dir = os.path.join(PathManager.get_tests_dir(), target)
        if not os.path.exists(tests_dir):
            path_warning(tests_dir)
            return test_list

        logger.debug("Path %s found. Checking content ...", tests_dir)
        for dir_path, sub_dirs, all_files in PathManager.sorted_walk(
                tests_dir):
            for current_file in all_files:
                directory = "%s%s%s" % (os.sep, core_args.directory, os.sep)
                include_params = [include]
                exclude_params = [exclude]
                if "," in include:
                    include_params = include.split(",")
                if "," in exclude:
                    exclude_params = exclude.split(",")
                current_full_path = os.path.join(dir_path, current_file)
                if current_file.endswith(
                        ".py") and not current_file.startswith("__"):
                    if include == "" and exclude == "" and directory == "":
                        if current_full_path not in test_list:
                            test_list.append(current_full_path)
                    else:
                        if core_args.directory == "" or directory in current_full_path:
                            for include_param in include_params:
                                if (include_param == ""
                                        or include_param in current_full_path):
                                    for exclude_param in exclude_params:
                                        if exclude_param == "":
                                            if current_full_path not in test_list:
                                                test_list.append(
                                                    current_full_path)
                                        else:
                                            if exclude_param not in current_full_path:
                                                if current_full_path not in test_list:
                                                    test_list.append(
                                                        current_full_path)
        if len(test_list) == 0:
            logger.error(
                "'%s' does not contain tests based on your search criteria. Exiting program."
                % tests_dir)
        else:
            logger.debug("List of all tests found: [%s]" %
                         ", ".join(map(str, test_list)))

    return test_list
Пример #7
0
def scan_all_tests():
    tests_directory = PathManager.get_tests_dir()
    logger.debug("Path %s found. Checking content ...", tests_directory)

    test_list = {}
    rootdir = tests_directory.rstrip(os.sep)
    start = rootdir.rfind(os.sep) + 1
    exclude_dirs = {"images", ".pytest_cache", "__pycache__"}
    exclude_files = {"__init__.py", "pytest.ini", ".DS_Store"}

    for path, dirs, files in PathManager.sorted_walk(rootdir):
        [dirs.remove(d) for d in list(dirs) if d in exclude_dirs]
        [files.remove(d) for d in list(files) if d in exclude_files]

        folders = path[start:].split(os.sep)
        subdir = dict.fromkeys(files)
        parent = reduce(dict.get, folders[:-1], test_list)
        parent[folders[-1]] = subdir

        if len(files) > 0:
            if os.path.isdir(path):
                my_plugin = TestCollector()
                pytest.main(["--collect-only", "-p", "no:terminal", path],
                            plugins=[my_plugin])
                for module in my_plugin.get_collected_items():
                    try:
                        module_path = str(module.fspath)
                        module_name = os.path.basename(module_path)
                        temp = module_path.split(
                            "%stests%s" %
                            (os.sep, os.sep))[1].split(module_name)[0]
                        package = os.path.join("tests", temp)
                        current_test = module.own_markers[0].kwargs
                        test_object = {
                            "name": module_name,
                            "module": module_path,
                            "description": current_test.get("description"),
                            "package": package,
                        }
                        if not current_test.get("values"):
                            pass
                        else:
                            for value in current_test.get("values").kwargs:
                                test_object[value] = current_test.get(
                                    "values").kwargs[value]
                        subdir[module_name] = test_object

                    except TypeError as e:
                        logger.warning("Error in test - %s: %s" %
                                       (module, e.message))
                    except AttributeError:
                        logger.warning("[%s] is not a test file. Skipping...",
                                       module)
    return test_list
Пример #8
0
    def send_json_report(self):
        report_s = validate_section('Report_URL')
        if len(report_s) > 0:
            logger.warning(
                '{}. \nJSON report cannot be sent - no report URL found in config file.'
                .format(report_s))
        else:
            run_file = os.path.join(PathManager.get_current_run_dir(),
                                    'run.json')
            url = get_config_property('Report_URL', 'url')
            if url is not None:
                try:
                    with open(run_file, 'rb') as file:
                        r = requests.post(url=url, files={'file': file})

                    if not r.ok:
                        logger.error(
                            'Report was not sent to URL: %s \nResponse text: %s'
                            % url, r.text)

                    logger.debug('Sent JSON report status: %s' % r.text)
                except requests.RequestException as ex:
                    logger.error(
                        'Failed to send run report to URL: %s \nException data: %s'
                        % url, ex)
            else:
                logger.error('Bad URL for JSON report.')
Пример #9
0
def save_failed_tests(test_list):
    failed_tests_file = os.path.join(PathManager.get_working_dir(),
                                     "lastfail.txt")
    with open(failed_tests_file, "w") as f:
        for test in test_list:
            f.write(test + "\n")
    f.close()
Пример #10
0
    def send_json_report(self):
        report_s = validate_section("Report_URL")
        if len(report_s) > 0:
            logger.warning(
                "{}. \nJSON report cannot be sent - no report URL found in config file."
                .format(report_s))
        else:
            run_file = os.path.join(PathManager.get_current_run_dir(),
                                    "run.json")
            url = get_config_property("Report_URL", "url")
            if url is not None:
                try:
                    with open(run_file, "rb") as file:
                        r = requests.post(url=url, files={"file": file})

                    if not r.ok:
                        logger.error(
                            "Report was not sent to URL: %s \nResponse text: %s"
                            % url, r.text)

                    logger.debug("Sent JSON report status: %s" % r.text)
                except requests.RequestException as ex:
                    logger.error(
                        "Failed to send run report to URL: %s \nException data: %s"
                        % url, ex)
            else:
                logger.error("Bad URL for JSON report.")
Пример #11
0
    def __init__(self):
        BaseTarget.__init__(self)
        global target_args
        target_args = self.get_target_args()
        self.target_name = "Firefox"
        self.process_list = []
        self.cc_settings = [
            {
                "name":
                "firefox",
                "type":
                "list",
                "label":
                "Firefox",
                "value":
                ["local", "latest", "latest-esr", "latest-beta", "nightly"],
                "default":
                "beta",
            },
            {
                "name": "locale",
                "type": "list",
                "label": "Locale",
                "value": OSHelper.LOCALES,
                "default": "en-US"
            },
            {
                "name": "max_tries",
                "type": "list",
                "label": "Maximum tries per test",
                "value": ["1", "2", "3", "4", "5"],
                "default": "3",
            },
            {
                "name": "highlight",
                "type": "checkbox",
                "label": "Debug using highlighting"
            },
            {
                "name": "override",
                "type": "checkbox",
                "label": "Run disabled tests"
            },
            {
                "name": "email",
                "type": "checkbox",
                "label": "Email results"
            },
            {
                "name": "report",
                "type": "checkbox",
                "label": "Create TestRail report"
            },
        ]

        self.local_web_root = os.path.join(PathManager.get_module_dir(),
                                           "targets", "firefox", "local_web")
        if target_args.treeherder:
            Settings.debug_image = False
Пример #12
0
def initialize_logger():
    logging.basicConfig(filename=PathManager.get_log_file_path(),
                        format=set_log_format())
    initialize_logger_level(core_args.level)

    # Control pytest terminal output via environment variable instead of parameter.
    if core_args.level > 10:
        os.environ["PYTEST_ADDOPTS"] = "-p no:terminal"
Пример #13
0
def update_run_index(app, finished=False):
    if finished:
        failed = 0
        total_duration = 0
        for test in app.completed_tests:
            if test.outcome == "FAILED" or test.outcome == "ERROR":
                failed = failed + 1
            total_duration = total_duration + test.test_duration

        current_run = {
            "duration": total_duration,
            "failed": failed,
            "id": PathManager.get_run_id(),
            "locale": args.locale,
            "target": args.target,
            "total": len(app.completed_tests),
        }
    else:
        current_run = {
            "duration": "-1",
            "failed": "-1",
            "id": PathManager.get_run_id(),
            "locale": args.locale,
            "target": args.target,
            "total": "-1",
        }

    run_file = os.path.join(PathManager.get_working_dir(), "data", "runs.json")

    if os.path.exists(run_file):
        logger.debug("Updating run file: %s" % run_file)
        with open(run_file, "r") as f:
            run_file_data = json.load(f)
        for run in run_file_data["runs"]:
            if run["id"] == PathManager.get_run_id():
                run_file_data["runs"].remove(run)
        run_file_data["runs"].append(current_run)
    else:
        logger.debug("Creating run file: %s" % run_file)
        run_file_data = {"runs": []}
        run_file_data["runs"].append(current_run)

    with open(run_file, "w") as f:
        json.dump(run_file_data, f, sort_keys=True, indent=True)
        f.close()
Пример #14
0
def exit_iris(message, status=0):
    if status == 0:
        logger.info(message)
    elif status == 1:
        logger.error(message)
    else:
        logger.debug(message)
    delete(PathManager.get_run_id(), update_run_file=False)
    ShutdownTasks.at_exit()
    exit(status)
Пример #15
0
    def _get_staged_profile(profile_name, path):
        """
        Internal-only method used to extract a given profile.
        :param profile_name:
        :param path:
        :return:
        """
        staged_profiles = os.path.join(PathManager.get_module_dir(), "targets", "firefox", "firefox_app", "profiles")

        sz_bin = find_executable("7z")
        logger.debug('Using 7zip executable at "%s"' % sz_bin)

        zipped_profile = os.path.join(staged_profiles, "%s.zip" % profile_name.value)

        cmd = [sz_bin, "x", "-y", "-bd", "-o%s" % staged_profiles, zipped_profile]
        logger.debug('Unzipping profile with command "%s"' % " ".join(cmd))
        try:
            output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
        except subprocess.CalledProcessError as e:
            logger.error("7zip failed: %s" % repr(e.output))
            raise Exception("Unable to unzip profile.")
        logger.debug("7zip succeeded: %s" % repr(output))

        from_directory = os.path.join(staged_profiles, profile_name.value)
        to_directory = "%s_%s" % (path, datetime.datetime.now().strftime("%Y%m%d%H%M%S"))

        if os.path.exists(path):
            try:
                shutil.rmtree(path)
                time.sleep(3)
            except Exception as e:
                logger.debug("Error, can't remove previous profile: %s" % e)

        logger.debug("Creating new profile: %s" % to_directory)

        try:
            logger.debug("From directory: %s" % from_directory)
            logger.debug("To directory: %s" % to_directory)
            dir_util.copy_tree(from_directory, to_directory)
        except Exception as e:
            logger.error("Error upon creating profile: %s" % e)

        try:
            shutil.rmtree(from_directory)
        except WindowsError:
            logger.debug("Error, can't remove orphaned directory, leaving in place.")

        resource_fork_folder = os.path.join(staged_profiles, "__MACOSX")
        if os.path.exists(resource_fork_folder):
            try:
                shutil.rmtree(resource_fork_folder)
            except WindowsError:
                logger.debug("Error, can't remove orphaned directory, leaving in place.")

        return to_directory
Пример #16
0
def create_target_json():
    if not use_cached_target_file():
        logging.info("Preparing data for the Control Center.")
        logging.info("This may take a minute.")

        if os.path.exists(os.path.join(PathManager.get_module_dir(),
                                       "targets")):
            master_target_dir = os.path.join(PathManager.get_module_dir(),
                                             "targets")
        else:
            master_target_dir = os.path.join(Settings.PACKAGE_ROOT, "moziris",
                                             "targets")

        target_list = [
            f for f in os.listdir(master_target_dir)
            if not f.startswith("__") and not f.startswith(".")
        ]

        targets = []
        for item in target_list:
            try:
                target_tests = scan_all_tests(item)
                target_module = importlib.import_module("targets.%s.main" %
                                                        item)
                try:
                    target = target_module.Target()
                    targets.append({
                        "name": target.target_name,
                        "tests": target_tests,
                        "icon": "%s.png" % item,
                        "settings": target.cc_settings,
                    })
                except NameError:
                    logger.error("Can't find default Target class.")
            except ImportError as e:
                logger.error("Problems importing module '%s':\n%s" % (item, e))

        target_json = {"targets": targets}
        target_json_file = os.path.join(PathManager.get_working_dir(), "data",
                                        "targets.json")
        with open(target_json_file, "w") as f:
            json.dump(target_json, f, sort_keys=True, indent=True)
Пример #17
0
def submit_email_report(target, result):
    """ PLACEHOLDER FOR EMAIL REPORT
        :param test_results: TEST RESULT SESSION
        need to update with appliications and git object
    """
    logger.info(
        " --------------------------------------------------------- " +
        Color.BLUE + "Starting Email report:" + Color.END +
        " ----------------------------------------------------------\n")
    email_report = EmailClient()
    email_report.send_email_report(target, str(result),
                                   PathManager.get_git_details())
Пример #18
0
def init_control_center():
    cc_assets_path = os.path.join(
        os.path.realpath(os.path.split(__file__)[0] + "/.."), "control_center", "assets"
    )
    logger.debug(
        "Copying Control Center assets from %s to %s"
        % (cc_assets_path, PathManager.get_working_dir())
    )
    copy_tree(cc_assets_path, PathManager.get_working_dir())
    if os.path.exists(os.path.join(PathManager.get_module_dir(), "targets")):
        logger.debug("Looking for CC files in module directory.")
        targets_dir = os.path.join(PathManager.get_module_dir(), "targets")
    else:
        logger.debug("Looking for CC files in package directory.")
        targets_dir = os.path.join(Settings.PACKAGE_ROOT, "moziris", "targets")

    exclude_dirs = {"__pycache__"}
    for path, dirs, files in PathManager.sorted_walk(targets_dir):
        [dirs.remove(d) for d in list(dirs) if d in exclude_dirs]
        for target in dirs:
            src = os.path.join(targets_dir, target, "icon.png")
            dest = os.path.join(PathManager.get_working_dir(), "images", "%s.png" % target)
            try:
                shutil.copyfile(src, dest)
            except FileNotFoundError:
                logger.warning("Could not find icon file for target: %s" % target)
        break
    create_target_json()
Пример #19
0
def delete_all():
    """
    Delete each run in the runs.json file, one at a time.
    """
    logger.debug("Delete All command received.")
    run_file = os.path.join(PathManager.get_working_dir(), "data", "runs.json")

    with open(run_file, "r") as data:
        run_file_data = json.load(data)
        data.close()

    for run in run_file_data["runs"]:
        delete(run["id"])
Пример #20
0
def delete(args, update_run_file=True):
    """
    Delete a past run.
    :param args: The run ID to delete
    :param update_run_file: Remove entry from runs.json file
    """
    logger.debug("Received delete command with arguments: %s " % args)

    if update_run_file:
        # Load run log JSON, find entry that matches the argument and delete it.
        # Then, write new run log file.
        run_file = os.path.join(PathManager.get_working_dir(), "data",
                                "runs.json")
        if os.path.exists(run_file):
            logger.debug("Deleting entry %s from run file: %s" %
                         (args, run_file))
            with open(run_file, "r") as data:
                run_file_data = json.load(data)
            found = False
            for run in run_file_data["runs"]:
                if run["id"] == args:
                    run_file_data["runs"].remove(run)
                    found = True
            if found:
                with open(run_file, "w") as data:
                    json.dump(run_file_data, data, sort_keys=True, indent=True)
            else:
                logger.error("Entry for run %s not found in run log file." %
                             args)
        else:
            logger.error("Run file not found.")

    # Remove run directory on disk.
    target_run = os.path.join(PathManager.get_working_dir(), "runs", args)
    if os.path.exists(target_run):
        shutil.rmtree(target_run, ignore_errors=True)
    else:
        logger.debug("Run directory does not exist: %s" % target_run)
Пример #21
0
def scan_all_tests(target):
    logging.info("Gathering test info for '%s'..." % target)
    master_test_root = os.path.join(PathManager.get_module_dir(), "tests")
    test_root = os.path.join(master_test_root, target)
    base_props = ["description"]
    tests = []

    my_plugin = TestCollector()
    pytest.main(["--collect-only", "-s", "-p", "no:terminal", test_root],
                plugins=[my_plugin])

    for test in my_plugin.get_collected_items():
        original_path = str(test.__dict__.get("fspath"))
        target_root = original_path.split(master_test_root)[1]
        test_path = target_root.split("%s%s%s" % (os.sep, target, os.sep))[1]
        parent = tests
        details = get_test_markers(test)
        for module in test_path.split(os.sep):
            test_obj = {"name": module.split(".py")[0]}
            if "py" not in module:
                module_exists = False
                for objects in parent:
                    if objects["name"] == module:
                        parent = objects["children"]
                        module_exists = True
                        break
                if not module_exists:
                    new_parent = test_obj["children"] = []
                    parent.append(test_obj)
                    parent = new_parent
            else:
                for prop in base_props:
                    if details.get(prop) is not None:
                        test_obj[prop] = details.get(prop)
                    else:
                        test_obj[prop] = ""
                test_obj["file"] = original_path
                values = {}
                for i in details:
                    if i not in base_props:
                        values[i] = details.get(i)
                if details.get("platform") is None:
                    values["platform"] = "all"
                if details.get("locale") is None:
                    values["locale"] = "all"
                test_obj["values"] = values
                parent.append(test_obj)
                parent = tests
    return tests
Пример #22
0
 def get_file_attachment():
     test_report_file = os.path.join(PathManager.get_current_run_dir(),
                                     "iris_log.log")
     if os.path.exists(test_report_file):
         file_log = open(test_report_file)
         attachment = MIMEText(file_log.read(), 1)
         file_log.close()
         attachment.add_header(
             "Content-Disposition",
             "attachment",
             filename=os.path.basename(test_report_file),
         )
         return attachment
     else:
         raise Exception("File %s is not present in path" %
                         test_report_file)
Пример #23
0
 def __init__(self):
     BaseTarget.__init__(self)
     global target_args
     target_args = self.get_target_args()
     self.target_name = 'Nightly'
     self.process_list = []
     self.cc_settings = [{
         'name': 'nightly',
         'type': 'list',
         'label': 'Nightly',
         'value': ['local', 'latest', 'nightly'],
         'default': 'nightly'
     }, {
         'name': 'locale',
         'type': 'list',
         'label': 'Locale',
         'value': OSHelper.LOCALES,
         'default': 'en-US'
     }, {
         'name': 'max_tries',
         'type': 'list',
         'label': 'Maximum tries per test',
         'value': ['1', '2', '3', '4', '5'],
         'default': '3'
     }, {
         'name': 'highlight',
         'type': 'checkbox',
         'label': 'Debug using highlighting'
     }, {
         'name': 'override',
         'type': 'checkbox',
         'label': 'Run disabled tests'
     }, {
         'name': 'email',
         'type': 'checkbox',
         'label': 'Email results'
     }, {
         'name': 'report',
         'type': 'checkbox',
         'label': 'Create TestRail report'
     }]
     self.local_web_root = os.path.join(PathManager.get_module_dir(),
                                        'targets', 'firefox', 'local_web')
     if target_args.treeherder:
         Settings.debug_image = False
Пример #24
0
def use_cached_target_file():
    """
    Helper function to determine if target.json is relatively recent and can be re-used.
    :return: True/False
    """
    # We will cache the target file for t5 minutes - adjust below if desired.
    cache_time = 60 * 15

    result = False
    target_json_file = os.path.join(PathManager.get_working_dir(), "data",
                                    "targets.json")
    if os.path.exists(target_json_file):
        file_modified_time = int(os.path.getmtime(target_json_file))
        logger.debug("Target file created: %s" % file_modified_time)
        current_time = int(time.mktime(datetime.now().timetuple()))
        logger.debug("Current time: %s" % current_time)
        elapsed_time = current_time - file_modified_time
        logger.debug("Elapsed time: %s" % elapsed_time)
        if elapsed_time < cache_time:
            result = True
    return result
Пример #25
0
    def _get_staged_profile(profile_name, path):
        """
        Internal-only method used to extract a given profile.
        :param profile_name:
        :param path:
        :return:
        """
        staged_profiles = os.path.join(PathManager.get_module_dir(), 'targets',
                                       'firefox', 'firefox_app', 'profiles')

        sz_bin = find_executable('7z')
        logger.debug('Using 7zip executable at "%s"' % sz_bin)

        zipped_profile = os.path.join(staged_profiles,
                                      '%s.zip' % profile_name.value)

        cmd = [
            sz_bin, 'x', '-y', '-bd',
            '-o%s' % staged_profiles, zipped_profile
        ]
        logger.debug('Unzipping profile with command "%s"' % ' '.join(cmd))
        try:
            output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
        except subprocess.CalledProcessError as e:
            logger.error('7zip failed: %s' % repr(e.output))
            raise Exception('Unable to unzip profile.')
        logger.debug('7zip succeeded: %s' % repr(output))

        from_directory = os.path.join(staged_profiles, profile_name.value)
        to_directory = '%s_%s' % (
            path, datetime.datetime.now().strftime('%Y%m%d%H%M%S'))

        if os.path.exists(path):
            try:
                shutil.rmtree(path)
                time.sleep(3)
            except Exception as e:
                logger.debug('Error, can\'t remove previous profile: %s' % e)

        logger.debug('Creating new profile: %s' % to_directory)

        try:
            logger.debug('From directory: %s' % from_directory)
            logger.debug('To directory: %s' % to_directory)
            dir_util.copy_tree(from_directory, to_directory)
        except Exception as e:
            logger.error('Error upon creating profile: %s' % e)

        try:
            shutil.rmtree(from_directory)
        except WindowsError:
            logger.debug(
                'Error, can\'t remove orphaned directory, leaving in place.')

        resource_fork_folder = os.path.join(staged_profiles, '__MACOSX')
        if os.path.exists(resource_fork_folder):
            try:
                shutil.rmtree(resource_fork_folder)
            except WindowsError:
                logger.debug(
                    'Error, can\'t remove orphaned directory, leaving in place.'
                )

        return to_directory
Пример #26
0
 def pytest_runtest_setup(self, item):
     os.environ["CURRENT_TEST"] = str(item.__dict__.get("fspath"))
     Settings.debug_image_path = PathManager.get_debug_image_directory()
Пример #27
0
def create_run_log(app):
    args = get_core_args()
    meta = {
        "run_id":
        PathManager.get_run_id(),
        "platform":
        OSHelper.get_os().value,
        "config":
        "%s, %s-bit, %s" % (OSHelper.get_os_version(), OSHelper.get_os_bits(),
                            OSHelper.get_processor()),
        "locale":
        args.locale,
        "args":
        " ".join(sys.argv),
        "params":
        vars(args),
        "log":
        os.path.join(PathManager.get_current_run_dir(), "iris_log.log"),
    }
    values = {}
    for i in app.values:
        values[i] = app.values[i]
    meta["values"] = values

    meta["iris_version"] = 2.0
    try:
        repo = git.Repo(PathManager.get_module_dir())
        meta["iris_repo"] = repo.working_tree_dir
        try:
            meta["iris_branch"] = repo.active_branch.name
        except:
            # If we're on a detached head, the active_branch is
            # undefined and raises an exception. This at least
            # allows the test run to finish
            meta["iris_branch"] = "detached"
        meta["iris_branch_head"] = repo.head.object.hexsha
    except:
        # Iris is not running in a Git repo, so don't try to
        # report on non-existent data.
        meta["iris_repo"] = "n/a"
        meta["iris_branch"] = "n/a"
        meta["iris_branch_head"] = "n/a"

    meta["python_version"] = get_python_version()

    failed = 0
    passed = 0
    skipped = 0
    errors = 0

    for test in app.completed_tests:
        if test.outcome == "FAILED":
            failed = failed + 1
        if test.outcome == "PASSED":
            passed = passed + 1
        if test.outcome == "SKIPPED":
            skipped = skipped + 1
        if test.outcome == "ERROR":
            errors = errors + 1

    logger.debug("Updating run.json with completed run data.")
    meta["total"] = len(app.completed_tests)
    meta["passed"] = passed
    meta["failed"] = failed
    meta["skipped"] = skipped
    meta["errors"] = errors
    meta["start_time"] = app.start_time
    meta["end_time"] = app.end_time
    meta["total_time"] = app.end_time - app.start_time

    tests = {
        "all_tests": convert_test_list(app.completed_tests),
        "failed_tests": convert_test_list(app.completed_tests,
                                          only_failures=True),
        "flaky_tests": app.flaky_tests,
    }

    run_file = os.path.join(PathManager.get_current_run_dir(), "run.json")
    run_file_data = {"meta": meta, "tests": tests}

    with open(run_file, "w") as f:
        json.dump(run_file_data, f, sort_keys=True, indent=True)
Пример #28
0
def convert_test_list(test_list, only_failures=False):
    """Takes a flat list of test objects and paths and converts to an object that can be serialized as JSON.

    :param test_list: List of completed tests
    :param only_failures: If True, only return failed tests
    :return:
    """
    test_root = os.path.join(PathManager.get_module_dir(), "tests")
    tests = []
    for test in test_list:
        test_failed = (True if "FAILED" in test.outcome
                       or "ERROR" in test.outcome else False)
        original_path = str(test.item.__dict__.get("fspath"))
        try:
            target_root = original_path.split(test_root)[1]
        except IndexError:
            logger.error("Error parsing test list.")
            logger.error(
                "Try resetting your PYTHONPATH before your next run, i.e.:")
            if OSHelper.get_os().value == "win":
                logger.error("\tsetx PYTHONPATH %CD%")
            else:
                logger.error("\texport PYTHONPATH=$PWD")
            return tests

        target = target_root.split(os.sep)[1]
        test_path = target_root.split("%s%s%s" % (os.sep, target, os.sep))[1]
        parent = tests
        details = get_test_markers(test.item)
        for module in test_path.split(os.sep):
            test_obj = {"name": module.split(".py")[0]}
            if "py" not in module:
                module_exists = False
                for objects in parent:
                    if objects["name"] == module:
                        parent = objects["children"]
                        module_exists = True
                        break
                if not module_exists:
                    new_parent = test_obj["children"] = []
                    if only_failures and test_failed:
                        parent.append(test_obj)
                    elif not only_failures:
                        parent.append(test_obj)
                    parent = new_parent
            else:
                if test_failed:
                    test_assert = {
                        "error": test.error.lstrip(),
                        "message": test.message.lstrip(),
                        "call_stack": test.traceback + "\n\n ",
                        "code": get_failing_code(test.node_name,
                                                 int(test.line)),
                    }
                    test_obj["assert"] = test_assert
                test_obj["result"] = test.outcome
                test_obj["time"] = test.test_duration
                debug_image_directory = os.path.join(
                    PathManager.get_current_run_dir(),
                    test_path.split(".py")[0],
                    "debug_images",
                )
                test_obj["debug_image_directory"] = debug_image_directory
                test_obj["debug_images"] = get_image_names(
                    debug_image_directory)
                test_obj["description"] = details.get("description")

                values = {}
                for i in details:
                    if i != "description":
                        values[i] = details.get(i)
                test_obj["values"] = values
                if only_failures and test_failed:
                    parent.append(test_obj)
                elif not only_failures:
                    parent.append(test_obj)
                parent = tests
    return tests
Пример #29
0
    def at_exit():
        reset_terminal_encoding()

        if os.path.exists(PathManager.get_temp_dir()):
            shutil.rmtree(PathManager.get_temp_dir(), ignore_errors=True)
Пример #30
0
def initialize_platform(args):
    init()
    fix_terminal_encoding()
    migrate_data()
    PathManager.create_working_directory()
    PathManager.create_run_directory()