def main():
    log_new('_main')

    parameters = get_parameters()

    config = Config()

    prepare_dir_structure(config)

    build_number = str(parameters.build_number)
    check_build_status(build_number, config)

    artifact_file_name = get_teamcity_artifact_file_name(build_number, config)
    artifact_url = get_teamcity_artifact_url(build_number, artifact_file_name, config)
    artifact_file = os.path.join(config.TEMP_ARTIFACTS_DIR, artifact_file_name)

    download_teamcity_artifact(artifact_url, artifact_file)

    unzip(artifact_file, config.TEMP_ARTIFACTS_DIR)

    check_artifacts(config.TEMP_ARTIFACTS_DIR, config)

    delete_unnecessary_artifacts(config.TEMP_ARTIFACTS_DIR, config)

    rename_artifacts(build_number, config.TEMP_ARTIFACTS_DIR)

    return 0
Пример #2
0
def compare_images(process_list, diff_dir, rgb_threshold, size_threshold,
                   config):
    """
    Image comparison: cycle through list of image pairs creating corresponding diffs
    
    :param process_list: list of image pairs (paths)
    :type process_list: [(list[str], list[str])]
    :param diff_dir: target diff directory
    :type diff_dir: str
    :param rgb_threshold: color filter threshold value in rgba units
    :type rgb_threshold: int
    :param size_threshold: size filter threshold value in pixels
    :type size_threshold: int
    :param config: configuration
    :type config: Config
    :return: namedtuple containing paths of initial images and created diff (l_image_path, r_image_path, diff_path)
    :rtype: list[ImageSet]
    """

    log_new('compare_images')

    assert isinstance(process_list, list)
    assert isinstance(diff_dir, str)

    return [
        ImageSet(
            correct_name, l_image_path, r_image_path,
            _compare_pair(l_image_path, r_image_path, diff_dir, rgb_threshold,
                          size_threshold, config.WHITENING_RATIO))
        for correct_name, l_image_path, r_image_path in process_list
    ]
Пример #3
0
def adb_load_base(config, parameters):
    log_new('load_base')

    [
        base,
        device_name,
    ] = parameters

    base_name = os.path.basename(base)

    logg('base', base)
    logg('device_name', device_name)

    adb_client = get_adb_client()

    adb_device = AdbDevice(device_name, config, adb_client)

    adb_device.echo('Recreating work dir {}'.format(config.ANDROID_WORK_DIR))
    if config.ANDROID_WORK_DIR == config.ANDROID_MAIN_DIR:
        raise Exception('Incorrect work dir: {}'.format(
            config.ANDROID_WORK_DIR))
    adb_device.delete_path_on_android(config.ANDROID_WORK_DIR)
    adb_device.create_dir_on_android(config.ANDROID_WORK_DIR)

    adb_device.echo('Loading base to Android device: {}'.format(device_name))
    adb_device.copy_file_to_android(
        base, '{}/{}'.format(config.ANDROID_WORK_DIR, base_name))

    adb_device.list_dir_content_on_android(config.ANDROID_WORK_DIR)

    adb_device.echo('Loading base finished')
Пример #4
0
def _get_parameters():
    log_new('_get_parameters')

    logg('cl', sys.argv)

    parser = argparse.ArgumentParser()
    parser.add_argument("--current-results-build", type=str,
                        required=False)  #left for backward compatability
    parser.add_argument("--baseline-results-build", type=str,
                        required=False)  #left for backward compatability
    parser.add_argument("--current-build", type=str, required=True)
    parser.add_argument("--baseline-build", type=str, required=True)
    parser.add_argument("--base-name", type=str, required=True)
    parser.add_argument("--test-name", type=str, required=True)
    parser.add_argument("--devices", type=str, required=True)
    parser.add_argument("--rgb-filter-threshold", type=str, required=True)
    parser.add_argument("--size-filter-threshold", type=str, required=True)
    parser.add_argument("--test-branch", type=str, required=True)
    parser.add_argument("--recreate-artifacts",
                        type=str,
                        default="false",
                        required=True)
    parser.add_argument("--qa-tcserver", type=str, required=True)

    parameters = parser.parse_args()
    logg('parameters', parameters)
    return parameters
def unzip(archive, path):
    log_new('unzip')
    logg('archive', archive)
    logg('path', path)

    with zipfile.ZipFile(archive, "r") as z:
        z.extractall(path)
Пример #6
0
    def check_result_file(cb, result_name):
        log_new('check_result_file')

        def is_existing_file(path):
            log_new('is_existing_file')
            return os.path.exists(path) and os.path.isfile(path)

        if 'current' in cb:
            cb_build = os.path.split(parameters.current_dir)[-1]
            cb_dir = parameters.current_dir
        elif 'baseline' in cb:
            cb_build = os.path.split(parameters.baseline_dir)[-1]
            cb_dir = parameters.baseline_dir

        if result_name == 'scenario':
            result_file_name = '_'.join((
                result_name,
                parameters.test_name,
                parameters.city_name
            )) + config.ARTIFACT_FORMAT
        else:
            result_file_name = '_'.join((
                result_name,
                parameters.device_name,
                parameters.test_name,
                parameters.city_name,
                cb_build
            )) + config.ARTIFACT_FORMAT

        result_file = os.path.join(cb_dir, result_file_name)
        logg('result_file', result_file)

        assert is_existing_file(result_file), 'result file not found: {}'.format(result_file)
def get_tags(tcserver_info, build_id):
    log_new('get_tags')

    url = ''.join((
        tcserver_info.url,
        '/app/rest/builds/buildType:',
        tcserver_info.project,
        ',id:',
        build_id,
        '/tags/',
    ))

    logg('url', url)

    response = requests.get(url,
                            auth=(tcserver_info.login, tcserver_info.password))
    answer = response.content
    logg('answer', answer)

    if response.status_code != 200:
        raise Exception(
            'Unable to get builds information from server, status code: {}'.
            format(str(response.status_code)))

    tags = parse_xml_answer(answer, "//tag/@name")

    return tags
Пример #8
0
def _run_results_comparison(device_name, parameters, config,
                            current_build_number, baseline_build_number,
                            current_results_build_number,
                            baseline_results_build_number, qa_tcserver_info2):
    log_new('_run_results_comparison')

    base_name = parameters.base_name
    test_name = parameters.test_name
    rgb_threshold = str(parameters.rgb_filter_threshold)
    size_threshold = str(parameters.size_filter_threshold)
    test_branch = parameters.test_branch

    qa_tc_project2_parameters = {
        '01_current_results_build': current_results_build_number,
        '02_baseline_results_build': baseline_results_build_number,
        '03_current_build_number': current_build_number,
        '04_baseline_build_number': baseline_build_number,
        '05_device_name': device_name,
        '06_test_name': test_name,
        '07_base_name': base_name,
        '08_rgb_threshold': rgb_threshold,
        '09_size_threshold': size_threshold,
    }
    qa_comment = _create_comment(
        device_name, test_name, base_name,
        '{} vs {}'.format(current_build_number, baseline_build_number))

    comparison_build_id = _run_build(config, qa_tcserver_info2,
                                     qa_tc_project2_parameters, test_branch,
                                     qa_comment, None)

    build_numbers = _wait_builds(config, qa_tcserver_info2,
                                 [comparison_build_id], [qa_comment])
    return build_numbers[comparison_build_id]
def run_process(config, cl):
    log_new('run_process')

    def wait_process(process, timeout):
        log_new('wait_process')

        start_time = time.time()
        wait_key = True
        while wait_key:
            time.sleep(config.PROCESS_WAIT_TIME_STEP_SEC)

            if process.poll() is None:  # process is running / not terminated
                current_time = time.time()
                seconds_passed = int(current_time - start_time)

                if seconds_passed > int(timeout):
                    log(' '.join(('timeout:', str(seconds_passed), 'sec')))
                    wait_key = False
                    subprocess.call(
                        ['taskkill', '/F', '/T', '/PID',
                         str(process.pid)])
                    log('process terminated')
            else:
                wait_key = False

    logg('cl', cl)
    process = subprocess.Popen(cl)
    wait_process(process, config.SHORT_TIMEOUT_SEC)
 def list_dir_content_on_android(self, dir_path):
     log_new('list_dir_content_on_android')
     logg('dir_path', dir_path)
     cl = 'ls {}'.format(dir_path)
     log('-------------------')
     self._execute_shell_command_on_device(cl)
     log('-------------------')
def get_test_data(parameters, config):
    log_new('prepare_test_data')

    artifacts = select_artifact(parameters.device_name, config)
    build_base = add_build_to_filename(artifacts.base, config.ARTIFACT_EXTENSIONS, parameters.build_number)
    build_dynamic_layout = add_build_to_filename(
        artifacts.dynamic_layout, config.ARTIFACT_EXTENSIONS, parameters.build_number)
    build_app = add_build_to_filename(artifacts.app, config.ARTIFACT_EXTENSIONS, parameters.build_number)
    scenario_name = '.'.join((parameters.test_name, 'json'))
    device_config_name = config.DEFAULT_DEVICE_CONFIG.replace('device', str(parameters.device_name))

    test_data = Data(
        base=os.path.join(config.TEMP_DATA_DIR, build_base),
        app_src=os.path.join(config.TEMP_DATA_DIR, build_app),
        scenario_name=scenario_name,
        scenario_src=os.path.join(config.ENV_TESTS_DIR, scenario_name),
        sh_script_src=os.path.join(config.ENV_SHELL_SCRIPTS_DIR, config.ANDROID_SIDE_RUN_SCRIPT_NAME),
        wait_script_src=os.path.join(config.ENV_PROJECT_DIR, config.WAIT_SCRIPT_NAME),
        result_screens_dir=os.path.join(config.TEMP_ARTIFACTS_DIR, 'screens'),
        result_logs_dir=os.path.join(config.TEMP_ARTIFACTS_DIR, 'logs'),
        device_config_src=os.path.join(config.ENV_CONFIG_DIR, device_config_name),
        device_config_name=device_config_name,
        log_name=config.LOG_NAME.replace('build', str(parameters.build_number)),
        dynamic_layout=os.path.join(config.TEMP_DATA_DIR, build_dynamic_layout),
    )

    logg('test_data', test_data)

    return test_data
def check_artifacts(artifact_path, config):
    log_new('_check_artifacts')

    artifacts = config.ARTIFACTS + config.ARTIFACTS_X86

    artifact_files = os.listdir(artifact_path)
    not_found_files = filter(lambda name: name not in artifact_files, artifacts)
    assert len(not_found_files) is 0, 'Artifact files not found: {}'.format(not_found_files)
Пример #13
0
def adb_restart(config):
    log_new('adb_restart')

    # use only at global start!

    kill_adb(config)
    start_adb(config)
    reconnect_offline(config)
Пример #14
0
def _set_comment(build_number, comment, tcserver_info):
    log_new('_set_comment')

    builds_info = get_builds(tcserver_info, build_number)
    build_info = builds_info[build_number]
    old_comment = build_info.comment
    build_id = build_info.id
    new_comment = '{}\n{}'.format(old_comment, comment)
    add_comment(build_id, new_comment, tcserver_info)
Пример #15
0
def main():
    log_new('_main')

    config = Config()

    parameters = get_parameters()
    check_input_data(parameters, config)

    return 0
def remove_files_if(func, files):
    log_new('remove_files_if')
    for file in files:
        if func(file):
            if os.path.isfile(file):
                logg('deleting file', file)
                os.remove(file)
            else:
                delete_directory(file)
def start_build(tcserver_info, tc_project_parameters_dict, branch, comment):
    log_new('start_build')

    url = tcserver_info.url + '/app/rest/buildQueue/'
    logg('url', url)

    parameters_row = ''
    for parameter_name, parameter_value in tc_project_parameters_dict.iteritems(
    ):
        parameters_row += '<property name="{}" value="{}"/>'.format(
            parameter_name, parameter_value)
    tc_project_parameters = '<properties>{}</properties>'.format(
        parameters_row)

    comment = '<comment><text>{}</text></comment>'.format(comment)

    if 'default' in branch.lower():
        branch = escape(branch)

    template = '<build branchName="{}"><buildType id={}/>{}{}</build>'.format(
        branch, '{id}', tc_project_parameters, comment)

    logg('template', template)

    headers = {'Content-Type': 'application/xml'}

    data = template.format(id=quoteattr(tcserver_info.project))

    logg('data', data)

    logg('login | password', '{} | {}'.format(tcserver_info.login,
                                              tcserver_info.password))

    response = requests.post(url,
                             headers=headers,
                             data=data,
                             auth=(tcserver_info.login,
                                   tcserver_info.password),
                             timeout=10)

    answer = response.content

    logg('answer', answer)

    if response.status_code != 200:
        raise Exception('Unable to start build, status code: {}'.format(
            str(response.status_code)))

    doc = etree.fromstring(answer.strip())
    values = doc.xpath("//build/@id")
    build_id = values[0]

    logg('values', values)
    logg('build_id', build_id)

    return build_id
Пример #18
0
def _run_build(config, qa_tcserver_info, qa_tc_project1_parameters_current,
               test_branch, qa_comment, remote_build_number):
    log_new('_run_build')
    build_id = start_build(qa_tcserver_info, qa_tc_project1_parameters_current,
                           test_branch, qa_comment)
    if build_id is None:
        _finalize_build(remote_build_number, False, config, qa_tcserver_info)

        raise Exception('Build not started!')
    return build_id
Пример #19
0
def _check_build_existence(build_number, tcserver_info):
    log_new('_check_build_existence')

    builds_info = get_builds(tcserver_info, build_number)

    if not builds_info:  #True if dict is empty
        raise Exception('Build #{} not found with scope depth {}'.format(
            build_number, tcserver_info.scope))
    else:
        log('Build #{} exists'.format(build_number))
def get_parameters():
    log_new('_get_parameters')

    logg('cl', sys.argv)

    parser = argparse.ArgumentParser()
    parser.add_argument("-b", "--build-number", type=str, required=True)
    args = parser.parse_args()
    logg('args', args)
    return args
 def get_build_url(build_number, build_fields):
     log_new('get_build_url')
     query_parameters = [
         ['fields', 'build(' + ','.join(build_fields) + ')'],
         ['locator', 'number:' + build_number],
     ]
     path = config.REMOTE_TC_SERVER_URL + '/app/rest/buildTypes/id:' + config.REMOTE_TC_PROJECT + '/builds'
     query = '&'.join(map(lambda pair: pair[0] + '=' + pair[1], query_parameters))
     url = path + '?' + query
     return url
Пример #22
0
def prepare_dir_structure(parameters, config):
    log_new('prepare_dir_structure')

    screens_diff_dir = os.path.join(parameters.diff_dir, 'screens')

    prepare_directory(screens_diff_dir)

    prepare_directory(config.TEMP_ARTIFACTS_DIR)

    return screens_diff_dir
Пример #23
0
def _finalize_build(build_number, is_qa_success, config, tcserver_info):
    log_new('_finalize_build')

    assert (build_number is not None)

    builds_info = get_builds(tcserver_info, build_number)

    if is_qa_success:
        _set_finished_tag(build_number, builds_info, config, tcserver_info)
    else:
        _set_broken_tag(build_number, builds_info, config, tcserver_info)
Пример #24
0
def _set_tag(chosen_build, builds_info, del_tags, new_tag, tcserver_info):
    log_new('_set_tag')
    log('{} -> {}'.format(del_tags, new_tag))

    build_info = builds_info[chosen_build]
    old_tags = set(build_info.tags)
    logg('old_tags', old_tags)
    tags_to_delete = set(del_tags)
    new_tags = (old_tags - tags_to_delete) | {new_tag}

    add_tags(chosen_build, new_tags, tcserver_info)
def check_input_artifacts(artifacts_path, build_number, device, config):
    log_new('check_input_artifacts')
    logg('artifacts_path', artifacts_path)

    artifacts = select_artifact(device, config)
    artifact_files = os.listdir(artifacts_path)
    expected_artifact_files = map(lambda name: add_build_to_filename(name, config.ARTIFACT_EXTENSIONS, build_number),
                                  artifacts)
    logg('expected_artifact_files', expected_artifact_files)
    not_found_files = filter(lambda name: name not in artifact_files, expected_artifact_files)
    assert len(not_found_files) is 0, 'Artifact files not found: {}'.format(not_found_files)
def get_teamcity_artifact_file_name(build_number, config):
    log_new('get_artifact_file_name')

    artifact_file_name = ''.join((
        config.ARTIFACT_NAME,
        '-',
        build_number,
        config.ARTIFACT_FORMAT
    ))
    logg('artifact_file_name', artifact_file_name)
    return artifact_file_name
def get_parameters():
    log_new('_get_parameters')

    logg('cl', sys.argv)

    parser = argparse.ArgumentParser()
    parser.add_argument("-b", "--build-number", type=str, required=True)
    parser.add_argument("-d", "--device-name", type=str, required=True)
    parser.add_argument("-t", "--test-name", type=str, required=True)
    parameters = parser.parse_args()
    logg('parameters', parameters)
    return parameters
def delete_unnecessary_artifacts(artifact_path, config):
    log_new('delete_unnecessary_artifacts')

    artifact_files = map(lambda name: os.path.join(artifact_path, name), os.listdir(artifact_path))

    artifacts = config.ARTIFACTS + config.ARTIFACTS_X86

    @logging
    def delete_condition(name):
        return os.path.split(name)[1] not in artifacts

    remove_files_if(delete_condition, artifact_files)
 def parse_response(response, build_fields):
     log_new('parse_response')
     response_content = response.content
     root = etree.fromstring(response_content)
     node = root.xpath('/builds/build')[0]
     result = {}
     for field_name in build_fields:
         value = node.get(field_name)
         logg(field_name, value)
         assert value is not None
         result[field_name] = value
     return result
def get_teamcity_artifact_url(build_number, artifact_file_name, config):
    log_new('get_artifact_url')

    url = '/'.join((
        config.REMOTE_TC_SERVER_GUEST_URL,
        'repository/download',
        config.REMOTE_TC_PROJECT,
        build_number,
        artifact_file_name
    ))
    logg('url created', url)
    return url