# Copyright (c) 2016, the R8 project authors. Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.

# Different utility functions used accross scripts

import hashlib
import jdk
import json
import os
import re
import shutil
import subprocess
import sys
import tarfile
import tempfile
import zipfile

import defines
import historic_run
from thread_utils import print_thread

ANDROID_JAR_DIR = 'third_party/android_jar/lib-v{api}'
ANDROID_JAR = os.path.join(ANDROID_JAR_DIR, 'android.jar')
TOOLS_DIR = defines.TOOLS_DIR
REPO_ROOT = defines.REPO_ROOT
THIRD_PARTY = defines.THIRD_PARTY
BUNDLETOOL_JAR_DIR = os.path.join(THIRD_PARTY, 'bundletool/bundletool-1.11.0')
BUNDLETOOL_JAR = os.path.join(BUNDLETOOL_JAR_DIR, 'bundletool-all-1.11.0.jar')
MEMORY_USE_TMP_FILE = 'memory_use.tmp'
DEX_SEGMENTS_RESULT_PATTERN = re.compile('- ([^:]+): ([0-9]+)')

DEPENDENCIES_DIR = os.path.join(THIRD_PARTY, 'dependencies')

BUILD = os.path.join(REPO_ROOT, 'build')
BUILD_JAVA_MAIN_DIR = os.path.join(REPO_ROOT, 'd8_r8', 'main', 'build',
                                   'classes', 'java', 'main')
LIBS = os.path.join(BUILD, 'libs')
CUSTOM_CONVERSION_DIR = os.path.join(THIRD_PARTY, 'openjdk',
                                     'custom_conversion')
GENERATED_LICENSE_DIR = os.path.join(BUILD, 'generatedLicense')
SRC_ROOT = os.path.join(REPO_ROOT, 'src', 'main', 'java')
REPO_SOURCE = 'https://r8.googlesource.com/r8'

GRADLE_TASK_CLEAN_TEST = ':test:cleanTest'
GRADLE_TASK_CONSOLIDATED_LICENSE = ':main:consolidatedLicense'
GRADLE_TASK_DOWNLOAD_DEPS = ':shared:downloadDeps'
GRADLE_TASK_KEEP_ANNO_JAR = ':keepanno:keepAnnoAnnotationsJar'
GRADLE_TASK_KEEP_ANNO_LEGACY_JAR = ':keepanno:keepAnnoLegacyAnnotationsJar'
GRADLE_TASK_KEEP_ANNO_ANDROIDX_JAR = ':keepanno:keepAnnoAndroidXAnnotationsJar'
GRADLE_TASK_KEEP_ANNO_DOC = ':keepanno:keepAnnoAnnotationsDoc'
GRADLE_TASK_MAIN_COMPILE = ':main:compileJava'
GRADLE_TASK_R8 = ':main:r8WithRelocatedDeps'
GRADLE_TASK_R8LIB = ':test:assembleR8LibWithRelocatedDeps'
GRADLE_TASK_R8LIB_NO_DEPS = ':test:assembleR8LibNoDeps'
GRADLE_TASK_THREADING_MODULE_BLOCKING = ':main:threadingModuleBlockingJar'
GRADLE_TASK_THREADING_MODULE_SINGLE_THREADED = ':main:threadingModuleSingleThreadedJar'
GRADLE_TASK_SOURCE_JAR = ':test:packageSources'
GRADLE_TASK_SWISS_ARMY_KNIFE = ':main:swissArmyKnife'
GRADLE_TASK_KEEPANNOTOOLS = 'main:keepAnnoToolsWithRelocatedDeps'
GRADLE_TASK_KEEPANNOTOOLSLIB = 'test:keepAnnoToolsLib'
GRADLE_TASK_TEST = ':test:test'
GRADLE_TASK_ALL_TESTS_WITH_APPLY_MAPPING_JAR = ':test:rewriteTestsForR8LibWithRelocatedDeps'
GRADLE_TASK_TESTBASE_WITH_APPLY_MAPPING_JAR = ':test:rewriteTestBaseForR8LibWithRelocatedDeps'
GRADLE_TASK_TEST_DEPS_JAR = ':test:packageTestDeps'
GRADLE_TASK_TEST_BASE_JAR = ':test:relocateTestBaseForR8LibWithRelocatedDeps'
GRADLE_TASK_TEST_JAR = ':test:relocateTestsForR8LibWithRelocatedDeps'
GRADLE_TASK_TEST_UNZIP_TESTBASE = ':test:unzipTestBase'

R8 = 'r8'
R8LIB = 'r8lib'

ALL_DEPS_JAR = os.path.join(LIBS, 'deps_all.jar')
R8_JAR = os.path.join(LIBS, 'r8.jar')
R8LIB_JAR = os.path.join(LIBS, 'r8lib.jar')
R8LIB_MAP = '%s.map' % R8LIB_JAR
R8LIB_PARTITION_MAP = '%s_map.zip' % R8LIB_JAR
R8_SRC_JAR = os.path.join(LIBS, 'r8-src.jar')
R8LIB_EXCLUDE_DEPS_JAR = os.path.join(LIBS, 'r8lib-exclude-deps.jar')
R8_FULL_EXCLUDE_DEPS_JAR = os.path.join(LIBS, 'r8-full-exclude-deps.jar')
THREADING_MODULE_BLOCKING_JAR = os.path.join(LIBS,
                                             'threading-module-blocking.jar')
THREADING_MODULE_SINGLE_THREADED_JAR = os.path.join(
    LIBS, 'threading-module-single-threaded.jar')
KEEPANNOTOOLS_JAR = os.path.join(LIBS, 'keepanno-tools.jar')
KEEPANNOTOOLSLIB_JAR = os.path.join(LIBS, 'keepanno-toolslib.jar')
KEEPANNOTOOLSLIB_MAP = '%s.map' % R8LIB_JAR
KEEPANNOTOOLS_SRC_JAR = os.path.join(LIBS, 'r8-src.jar')

R8_TESTS_JAR = os.path.join(LIBS, 'r8tests.jar')
R8_TESTBASE_JAR = os.path.join(LIBS, 'r8test_base.jar')
R8LIB_TESTBASE_JAR = os.path.join(LIBS, 'r8libtestbase-cf.jar')
R8LIB_TESTS_JAR = os.path.join(LIBS, 'r8libtestdeps-cf.jar')
R8_TESTS_DEPS_JAR = os.path.join(LIBS, 'test_deps_all.jar')
R8LIB_TESTS_DEPS_JAR = R8_TESTS_DEPS_JAR
MAVEN_ZIP_LIB = os.path.join(LIBS, 'r8lib.zip')
LIBRARY_DESUGAR_CONVERSIONS_LEGACY_ZIP = os.path.join(
    CUSTOM_CONVERSION_DIR, 'library_desugar_conversions_legacy.jar')
LIBRARY_DESUGAR_CONVERSIONS_ZIP = os.path.join(
    CUSTOM_CONVERSION_DIR, 'library_desugar_conversions.jar')
KEEPANNO_ANNOTATIONS_JAR = os.path.join(LIBS, 'keepanno-annotations.jar')
KEEPANNO_ANNOTATIONS_DOC = os.path.join('d8_r8', 'keepanno', 'build', 'docs',
                                        'javadoc')
KEEPANNO_LEGACY_ANNOTATIONS_JAR = os.path.join(
    LIBS, 'keepanno-annotations-legacy.jar')
KEEPANNO_ANDROIDX_ANNOTATIONS_JAR = os.path.join(
    LIBS, 'keepanno-annotations-androidx.jar')

DESUGAR_CONFIGURATION = os.path.join('src', 'library_desugar',
                                     'desugar_jdk_libs.json')
DESUGAR_IMPLEMENTATION = os.path.join('third_party', 'openjdk',
                                      'desugar_jdk_libs',
                                      'desugar_jdk_libs.jar')
DESUGAR_CONFIGURATION_JDK11_LEGACY = os.path.join(
    'src', 'library_desugar', 'jdk11', 'desugar_jdk_libs_legacy.json')
DESUGAR_CONFIGURATION_JDK11_MINIMAL = os.path.join(
    'src', 'library_desugar', 'jdk11', 'desugar_jdk_libs_minimal.json')
DESUGAR_CONFIGURATION_JDK11 = os.path.join('src', 'library_desugar', 'jdk11',
                                           'desugar_jdk_libs.json')
DESUGAR_CONFIGURATION_JDK11_NIO = os.path.join('src', 'library_desugar',
                                               'jdk11',
                                               'desugar_jdk_libs_nio.json')
DESUGAR_IMPLEMENTATION_JDK11 = os.path.join('third_party', 'openjdk',
                                            'desugar_jdk_libs_11',
                                            'desugar_jdk_libs.jar')
DESUGAR_CONFIGURATION_MAVEN_ZIP = os.path.join(
    LIBS, 'desugar_jdk_libs_configuration.zip')
DESUGAR_CONFIGURATION_JDK11_LEGACY_MAVEN_ZIP = os.path.join(
    LIBS, 'desugar_jdk_libs_configuration_jdk11_legacy.zip')
DESUGAR_CONFIGURATION_JDK11_MINIMAL_MAVEN_ZIP = os.path.join(
    LIBS, 'desugar_jdk_libs_configuration_jdk11_minimal.zip')
DESUGAR_CONFIGURATION_JDK11_MAVEN_ZIP = os.path.join(
    LIBS, 'desugar_jdk_libs_configuration_jdk11.zip')
DESUGAR_CONFIGURATION_JDK11_NIO_MAVEN_ZIP = os.path.join(
    LIBS, 'desugar_jdk_libs_configuration_jdk11_nio.zip')
GENERATED_LICENSE = os.path.join(GENERATED_LICENSE_DIR, 'LICENSE')
RT_JAR = os.path.join(REPO_ROOT, 'third_party/openjdk/openjdk-rt-1.8/rt.jar')
R8LIB_KEEP_RULES = os.path.join(REPO_ROOT, 'src/main/keep.txt')
CF_SEGMENTS_TOOL = os.path.join(THIRD_PARTY, 'cf_segments')
PINNED_R8_JAR = os.path.join(REPO_ROOT, 'third_party/r8/r8.jar')
PINNED_PGR8_JAR = os.path.join(REPO_ROOT, 'third_party/r8/r8-pg6.0.1.jar')

OPENSOURCE_DUMPS_DIR = os.path.join(THIRD_PARTY, 'opensource-apps')
INTERNAL_DUMPS_DIR = os.path.join(THIRD_PARTY, 'internal-apps')
BAZEL_SHA_FILE = os.path.join(THIRD_PARTY, 'bazel.tar.gz.sha1')
BAZEL_TOOL = os.path.join(THIRD_PARTY, 'bazel')
JAVA8_SHA_FILE = os.path.join(THIRD_PARTY, 'openjdk', 'jdk8',
                              'linux-x86.tar.gz.sha1')
JAVA11_SHA_FILE = os.path.join(THIRD_PARTY, 'openjdk', 'jdk-11',
                               'linux.tar.gz.sha1')
JAVA17_SHA_FILE = os.path.join(THIRD_PARTY, 'openjdk', 'jdk-17',
                               'linux.tar.gz.sha1')
DESUGAR_JDK_LIBS_11_SHA_FILE = os.path.join(THIRD_PARTY, 'openjdk',
                                            'desugar_jdk_libs_11.tar.gz.sha1')
IGNORE_WARNINGS_RULES = os.path.join(REPO_ROOT, 'src', 'test',
                                     'ignorewarnings.rules')
ANDROID_HOME_ENVIROMENT_NAME = "ANDROID_HOME"
ANDROID_TOOLS_VERSION_ENVIRONMENT_NAME = "ANDROID_TOOLS_VERSION"
USER_HOME = os.path.expanduser('~')

R8_TEST_RESULTS_BUCKET = 'r8-test-results'
R8_INTERNAL_TEST_RESULTS_BUCKET = 'r8-internal-test-results'


def archive_file(name, gs_dir, src_file):
    gs_file = '%s/%s' % (gs_dir, name)
    upload_file_to_cloud_storage(src_file, gs_file)


def archive_value(name, gs_dir, value):
    with TempDir() as temp:
        temparchive = os.path.join(temp, name)
        with open(temparchive, 'w') as f:
            f.write(str(value))
        archive_file(name, gs_dir, temparchive)


def find_cloud_storage_file_from_options(name, options, orElse=None):
    # Import archive on-demand since archive depends on utils.
    from archive import GetUploadDestination
    hash_or_version = find_hash_or_version_from_options(options)
    if not hash_or_version:
        return orElse
    is_hash = options.commit_hash is not None
    download_path = GetUploadDestination(hash_or_version, name, is_hash)
    if file_exists_on_cloud_storage(download_path):
        out = tempfile.NamedTemporaryFile().name
        download_file_from_cloud_storage(download_path, out)
        return out
    else:
        raise Exception('Could not find file {} from hash/version: {}.'.format(
            name, hash_or_version))


def find_r8_jar_from_options(options):
    return find_cloud_storage_file_from_options('r8.jar', options)


def find_hash_or_version_from_options(options):
    if options.tag:
        return find_hash_or_version_from_tag(options.tag)
    else:
        return options.commit_hash or options.version


def find_hash_or_version_from_tag(tag_or_hash):
    info = subprocess.check_output(
        ['git', 'show', tag_or_hash, '-s',
         '--format=oneline']).decode('utf-8').splitlines()[-1].split()
    # The info should be on the following form [hash,"Version",version]
    if len(info) == 3 and len(info[0]) == 40 and info[1] == "Version":
        return info[2]
    return None


def getAndroidHome():
    return os.environ.get(ANDROID_HOME_ENVIROMENT_NAME,
                          os.path.join(USER_HOME, 'Android', 'Sdk'))


def getAndroidBuildTools():
    if ANDROID_TOOLS_VERSION_ENVIRONMENT_NAME in os.environ:
        version = os.environ.get(ANDROID_TOOLS_VERSION_ENVIRONMENT_NAME)
        build_tools_dir = os.path.join(getAndroidHome(), 'build-tools', version)
        assert os.path.exists(build_tools_dir)
        return build_tools_dir
    else:
        versions = ['35.0.1', '34.0.0', '33.0.1', '32.0.0']
        for version in versions:
            build_tools_dir = os.path.join(getAndroidHome(), 'build-tools',
                                           version)
            if os.path.exists(build_tools_dir):
                return build_tools_dir
    raise Exception('Unable to find Android build-tools')


def is_python3():
    return sys.version_info.major == 3


def Print(s, quiet=False):
    if quiet:
        return
    print(s)


def Warn(message):
    CRED = '\033[91m'
    CEND = '\033[0m'
    print(CRED + message + CEND)


def PrintCmd(cmd, env=None, quiet=False, worker_id=None):
    if quiet:
        return
    if type(cmd) is list:
        cmd = ' '.join(cmd)
    if env:
        env = ' '.join(['{}=\"{}\"'.format(x, y) for x, y in env.iteritems()])
        print_thread('Running: {} {}'.format(env, cmd), worker_id)
    else:
        print_thread('Running: {}'.format(cmd), worker_id)
    # I know this will hit os on windows eventually if we don't do this.
    sys.stdout.flush()


class ProgressLogger(object):
    CLEAR_LINE = '\033[K'
    UP = '\033[F'

    def __init__(self, quiet=False):
        self._count = 0
        self._has_printed = False
        self._quiet = quiet

    def log(self, text):
        if len(text.strip()) == 0:
            return
        if self._quiet:
            if self._has_printed:
                sys.stdout.write(ProgressLogger.UP + ProgressLogger.CLEAR_LINE)
            if len(text) > 140:
                text = text[0:140] + '...'
        print(text)
        self._has_printed = True

    def done(self):
        if self._quiet and self._has_printed:
            sys.stdout.write(ProgressLogger.UP + ProgressLogger.CLEAR_LINE)
            print('')
            sys.stdout.write(ProgressLogger.UP)


def RunCmd(cmd,
           env_vars=None,
           quiet=False,
           fail=True,
           logging=True,
           shell=False):
    PrintCmd(cmd, env=env_vars, quiet=quiet)
    env = os.environ.copy()
    if env_vars:
        env.update(env_vars)
    process = subprocess.Popen(cmd,
                               env=env,
                               shell=shell,
                               stdout=subprocess.PIPE,
                               stderr=subprocess.STDOUT)
    stdout = []
    logger = ProgressLogger(quiet=quiet) if logging else None
    failed = False
    while True:
        line = process.stdout.readline().decode('utf-8')
        if line != '':
            stripped = line.rstrip()
            stdout.append(stripped)
            if logger:
                logger.log(stripped)
            # TODO(christofferqa): r8 should fail with non-zero exit code.
            if ('AssertionError:' in stripped or
                    'CompilationError:' in stripped or
                    'CompilationFailedException:' in stripped or
                    'Compilation failed' in stripped or
                    'FAILURE:' in stripped or
                    'org.gradle.api.ProjectConfigurationException' in stripped
                    or 'BUILD FAILED' in stripped):
                failed = True
        else:
            if logger:
                logger.done()
            exit_code = process.poll()
            if exit_code or failed:
                for line in stdout:
                    Warn(line)
                if fail:
                    raise subprocess.CalledProcessError(
                        exit_code or -1, cmd, output='\n'.join(stdout))
            return stdout


def IsWindows():
    return defines.IsWindows()


def EnsureDepFromGoogleCloudStorage(dep, tgz, sha1, msg):
    if (not os.path.exists(dep) or not os.path.exists(tgz) or
            os.path.getmtime(tgz) < os.path.getmtime(sha1)):
        DownloadFromGoogleCloudStorage(sha1)
        # Update the mtime of the tar file to make sure we do not run again unless
        # there is an update.
        os.utime(tgz, None)
    else:
        print('Ensure cloud dependency:', msg, 'present')


def DownloadFromX20(sha1_file):
    download_script = os.path.join(REPO_ROOT, 'tools', 'download_from_x20.py')
    cmd = [download_script, sha1_file]
    PrintCmd(cmd)
    subprocess.check_call(cmd)


def DownloadFromGoogleCloudStorage(sha1_file,
                                   bucket='r8-deps',
                                   auth=False,
                                   quiet=False):
    suffix = '.bat' if IsWindows() else ''
    download_script = 'download_from_google_storage%s' % suffix
    cmd = [download_script]
    if not auth:
        cmd.append('-n')
    cmd.extend(['-b', bucket, '-u', '-s', sha1_file])
    if not quiet:
        PrintCmd(cmd)
        subprocess.check_call(cmd)
    else:
        subprocess.check_output(cmd)


def get_nth_sha1_from_revision(n, revision):
    result = subprocess.check_output([
        'git', 'log', revision, f'--skip={n}', '--max-count=1',
        '--pretty=format:%H'
    ]).decode('utf-8')
    return result.strip()


def get_sha1(filename):
    sha1 = hashlib.sha1()
    with open(filename, 'rb') as f:
        while True:
            chunk = f.read(1024 * 1024)
            if not chunk:
                break
            sha1.update(chunk)
    return sha1.hexdigest()


def get_sha1_from_revision(revision):
    cmd = ['git', 'rev-parse', revision]
    PrintCmd(cmd)
    with ChangedWorkingDirectory(REPO_ROOT):
        return subprocess.check_output(cmd).decode('utf-8').strip()


def get_HEAD_branch():
    result = subprocess.check_output(
        ['git', 'rev-parse', '--abbrev-ref', 'HEAD']).decode('utf-8')
    return result.strip()


def get_HEAD_commit():
    return historic_run.git_commit_from_hash(get_HEAD_sha1())


def get_HEAD_sha1():
    return get_sha1_from_revision('HEAD')


def get_HEAD_diff_stat():
    return subprocess.check_output(['git', 'diff', '--stat']).decode('utf-8')


def makedirs_if_needed(path):
    try:
        os.makedirs(path)
    except OSError:
        if not os.path.isdir(path):
            raise


def get_gsutil():
    return 'gsutil.py' if os.name != 'nt' else 'gsutil.py.bat'


def upload_file_to_cloud_storage(source, destination, header=None):
    cmd = [get_gsutil()]
    if header:
        cmd.extend(['-h', header])
    cmd.extend(['cp', source, destination])
    PrintCmd(cmd)
    subprocess.check_call(cmd)


def check_dir_args(source, destination):
    # We require that the dirname of the paths coincide, e.g., src/dirname and dst/dirname
    # The target is then stripped so the upload command will be: cp -R src/dirname dst/
    (destination_parent, destination_file) = os.path.split(destination)
    if os.path.basename(source) != destination_file:
        raise Exception(
            'Attempt to upload directory with non-matching directory name: ' +
            f'{source} and {destination}')
    if len(destination_parent.strip()) == 0:
        raise Exception(
            'Attempt to upload directory to empty destination directory: ' +
            destination)
    return destination_parent


def upload_directory_to_cloud_storage(source, destination, parallel=True):
    destination_parent = check_dir_args(source, destination)
    cmd = [get_gsutil()]
    if parallel:
        cmd += ['-m']
    cmd += ['cp', '-R']
    cmd += [source, destination_parent + '/']
    PrintCmd(cmd)
    subprocess.check_call(cmd)


def rsync_directory_to_cloud_storage(source, destination, parallel=True):
    check_dir_args(source, destination)
    cmd = [get_gsutil()]
    if parallel:
        cmd += ['-m']
    cmd += ['rsync', '-R']
    cmd += [source, destination]
    PrintCmd(cmd)
    subprocess.check_call(cmd)


def delete_file_from_cloud_storage(destination):
    cmd = [get_gsutil(), 'rm', destination]
    PrintCmd(cmd)
    subprocess.check_call(cmd)


def ls_files_on_cloud_storage(destination):
    cmd = [get_gsutil(), 'ls', destination]
    PrintCmd(cmd)
    return subprocess.check_output(cmd).decode('utf-8')


def cat_file_on_cloud_storage(destination, ignore_errors=False):
    cmd = [get_gsutil(), 'cat', destination]
    PrintCmd(cmd)
    try:
        return subprocess.check_output(cmd).decode('utf-8').strip()
    except subprocess.CalledProcessError as e:
        if ignore_errors:
            return ''
        else:
            raise e


def file_exists_on_cloud_storage(destination):
    cmd = [get_gsutil(), 'ls', destination]
    PrintCmd(cmd)
    return subprocess.call(cmd) == 0


def download_file_from_cloud_storage(source,
                                     destination,
                                     concurrent=False,
                                     flags=None,
                                     printcmd=True,
                                     quiet=False):
    cmd = [get_gsutil()]
    if concurrent:
        cmd.append('-m')
    if quiet:
        cmd.append('-q')
    cmd.append('cp')
    if flags:
        cmd.extend(flags)
    cmd.extend([source, destination])
    PrintCmd(cmd, quiet=not printcmd)
    subprocess.check_call(cmd)


def create_archive(name, sources=None):
    if not sources:
        sources = [name]
    tarname = '%s.tar.gz' % name
    with tarfile.open(tarname, 'w:gz') as tar:
        for source in sources:
            tar.add(source)
    return tarname


def extract_dir(filename):
    return filename[0:len(filename) - len('.tar.gz')]


def unpack_archive(filename):
    dest_dir = extract_dir(filename)
    if os.path.exists(dest_dir):
        print('Deleting existing dir %s' % dest_dir)
        shutil.rmtree(dest_dir)
    dirname = os.path.dirname(os.path.abspath(filename))
    with tarfile.open(filename, 'r:gz') as tar:
        tar.extractall(path=dirname)


def check_gcert():
    status = subprocess.call(['gcertstatus'])
    if status != 0:
        subprocess.check_call(['gcert'])


# Note that gcs is eventually consistent with regards to list operations.
# This is not a problem in our case, but don't ever use this method
# for synchronization.
def cloud_storage_exists(destination):
    cmd = [get_gsutil(), 'ls', destination]
    PrintCmd(cmd)
    exit_code = subprocess.call(cmd)
    return exit_code == 0


class TempDir(object):

    def __init__(self, prefix='', delete=True):
        self._temp_dir = None
        self._prefix = prefix
        self._delete = delete

    def __enter__(self):
        self._temp_dir = tempfile.mkdtemp(self._prefix)
        return self._temp_dir

    def __exit__(self, *_):
        if self._delete:
            shutil.rmtree(self._temp_dir, ignore_errors=True)


class ChangedWorkingDirectory(object):

    def __init__(self, working_directory, quiet=False):
        self._quiet = quiet
        self._working_directory = working_directory

    def __enter__(self):
        self._old_cwd = os.getcwd()
        if not self._quiet:
            print('Enter directory:', self._working_directory)
        os.chdir(self._working_directory)

    def __exit__(self, *_):
        if not self._quiet:
            print('Enter directory:', self._old_cwd)
        os.chdir(self._old_cwd)


# Reading Android CTS test_result.xml


class CtsModule(object):

    def __init__(self, module_name):
        self.name = module_name


class CtsTestCase(object):

    def __init__(self, test_case_name):
        self.name = test_case_name


class CtsTest(object):

    def __init__(self, test_name, outcome):
        self.name = test_name
        self.outcome = outcome


# Generator yielding CtsModule, CtsTestCase or CtsTest from
# reading through a CTS test_result.xml file.
def read_cts_test_result(file_xml):
    re_module = re.compile('<Module name="([^"]*)"')
    re_test_case = re.compile('<TestCase name="([^"]*)"')
    re_test = re.compile('<Test result="(pass|fail)" name="([^"]*)"')
    with open(file_xml) as f:
        for line in f:
            m = re_module.search(line)
            if m:
                yield CtsModule(m.groups()[0])
                continue
            m = re_test_case.search(line)
            if m:
                yield CtsTestCase(m.groups()[0])
                continue
            m = re_test.search(line)
            if m:
                outcome = m.groups()[0]
                assert outcome in ['fail', 'pass']
                yield CtsTest(m.groups()[1], outcome == 'pass')


def grep_memoryuse(logfile):
    re_vmhwm = re.compile('^VmHWM:[ \t]*([0-9]+)[ \t]*([a-zA-Z]*)')
    result = None
    with open(logfile) as f:
        for line in f:
            m = re_vmhwm.search(line)
            if m:
                groups = m.groups()
                s = len(groups)
                if s >= 1:
                    result = int(groups[0])
                    if s >= 2:
                        unit = groups[1]
                        if unit == 'kB':
                            result *= 1024
                        elif unit != '':
                            raise Exception(
                                'Unrecognized unit in memory usage log: {}'.
                                format(unit))
    if result is None:
        raise Exception('No memory usage found in log: {}'.format(logfile))
    return result


# Return a dictionary: {segment_name -> segments_size}
def getDexSegmentSizes(dex_files):
    assert len(dex_files) > 0
    cmd = [jdk.GetJavaExecutable(), '-jar', R8_JAR, 'dexsegments']
    cmd.extend(dex_files)
    PrintCmd(cmd)
    output = subprocess.check_output(cmd).decode('utf-8')

    matches = DEX_SEGMENTS_RESULT_PATTERN.findall(output)

    if matches is None or len(matches) == 0:
        raise Exception('DexSegments failed to return any output for' \
            ' these files: {}'.format(dex_files))

    result = {}

    for match in matches:
        result[match[0]] = int(match[1])

    return result


# Return a dictionary: {segment_name -> segments_size}
def getCfSegmentSizes(cfFile):
    cmd = [
        jdk.GetJavaExecutable(), '-cp', CF_SEGMENTS_TOOL,
        'com.android.tools.r8.cf_segments.MeasureLib', cfFile
    ]
    PrintCmd(cmd)
    output = subprocess.check_output(cmd).decode('utf-8')

    matches = DEX_SEGMENTS_RESULT_PATTERN.findall(output)

    if matches is None or len(matches) == 0:
        raise Exception('CfSegments failed to return any output for' \
                        ' the file: ' + cfFile)

    result = {}

    for match in matches:
        result[match[0]] = int(match[1])

    return result


def get_maven_path(artifact, version):
    return os.path.join('com', 'android', 'tools', artifact, version)


def print_cfsegments(prefix, cf_files):
    for cf_file in cf_files:
        for segment_name, size in getCfSegmentSizes(cf_file).items():
            print('{}-{}(CodeSize): {}'.format(prefix, segment_name, size))


def print_dexsegments(prefix, dex_files, worker_id=None):
    for segment_name, size in getDexSegmentSizes(dex_files).items():
        print_thread('{}-{}(CodeSize): {}'.format(prefix, segment_name, size),
                     worker_id)


# Ensure that we are not benchmarking with a google jvm.
def check_java_version():
    cmd = [jdk.GetJavaExecutable(), '-version']
    output = subprocess.check_output(cmd,
                                     stderr=subprocess.STDOUT).decode('utf-8')
    m = re.search('openjdk version "([^"]*)"', output)
    if m is None:
        raise Exception("Can't check java version: no version string in output"
                        " of 'java -version': '{}'".format(output))
    version = m.groups(0)[0]
    m = re.search('google', version)
    if m is not None:
        raise Exception("Do not use google JVM for benchmarking: " + version)


def api_str(api_level_major, api_level_minor):
    api = str(api_level_major)
    if api_level_minor > 0:
        api = api + '.' + str(api_level_minor)
    return api


def get_android_jar_dir(api_level_major, api_level_minor):
    return os.path.join(
        REPO_ROOT,
        ANDROID_JAR_DIR.format(api=api_str(api_level_major, api_level_minor)))


def get_android_jar(api_level_major, api_level_minor):
    return os.path.join(
        REPO_ROOT,
        ANDROID_JAR.format(api=api_str(api_level_major, api_level_minor)))


def is_bot():
    return 'SWARMING_BOT_ID' in os.environ


def uncompressed_size(path):
    return sum(z.file_size for z in zipfile.ZipFile(path).infolist())


def desugar_configuration_name_and_version(configuration, is_for_maven):
    name = 'desugar_jdk_libs_configuration'
    with open(configuration, 'r') as f:
        configuration_json = json.loads(f.read())
        configuration_format_version = \
            configuration_json.get('configuration_format_version')
        if (not configuration_format_version):
            raise Exception('No "configuration_format_version" found in ' +
                            configuration)
        if (configuration_format_version != 3 and
                configuration_format_version != 5 and
                configuration_format_version != (200 if is_for_maven else 101)):
            raise Exception(
                'Unsupported "configuration_format_version" "%s" found in %s' %
                (configuration_format_version, configuration))
        version = configuration_json.get('version')
        if not version:
            if configuration_format_version == (200 if is_for_maven else 101):
                identifier = configuration_json.get('identifier')
                if not identifier:
                    raise Exception('No "identifier" found in ' + configuration)
                identifier_split = identifier.split(':')
                if (len(identifier_split) != 3):
                    raise Exception('Invalid "identifier" found in ' +
                                    configuration)
                if (identifier_split[0] != 'com.tools.android'):
                    raise Exception('Invalid "identifier" found in ' +
                                    configuration)
                if not identifier_split[1].startswith(
                        'desugar_jdk_libs_configuration'):
                    raise Exception('Invalid "identifier" found in ' +
                                    configuration)
                name = identifier_split[1]
                version = identifier_split[2]
            else:
                raise Exception('No "version" found in ' + configuration)
        else:
            if configuration_format_version == (200 if is_for_maven else 101):
                raise Exception('No "version" expected in ' + configuration)
        # Disallow prerelease, as older R8 versions cannot parse it causing hard to
        # understand errors.
        check_basic_semver_version(version,
                                   'in ' + configuration,
                                   allowPrerelease=False)
        return (name, version)


class SemanticVersion:

    def __init__(self, major, minor, patch, prerelease):
        self.major = major
        self.minor = minor
        self.patch = patch
        self.prerelease = prerelease
        # Build metadata currently not suppported

    def larger_than(self, other):
        if self.major > other.major:
            return True
        if self.major == other.major and self.minor > other.minor:
            return True
        if self.patch:
            return (self.major == other.major and self.minor == other.minor and
                    self.patch > other.patch)
        if self.prerelease:
            if other.prerelease:
                return self.prerelease > other.prerelease
            else:
                return False

        else:
            return False


# Check that the passed string is formatted as a basic semver version (x.y.z or x.y.z-prerelease
# depending on the value of allowPrerelease).
# See https://semver.org/. The regexp parts used are not all complient with what is suggested
# on https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string.
def check_basic_semver_version(version,
                               error_context='',
                               components=3,
                               allowPrerelease=False):
    regexp = '^'
    for x in range(components):
        regexp += '([0-9]+)'
        if x < components - 1:
            regexp += '\\.'
    if allowPrerelease:
        # This part is from
        # https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string
        regexp += r'(?:-(?P<prerelease>(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?'
    regexp += '$'
    reg = re.compile(regexp)
    match = reg.match(version)
    if not match:
        raise Exception("Invalid version '" + version + "'" +
                        (' ' + error_context) if len(error_context) > 0 else '')
    if components == 2:
        return SemanticVersion(int(match.group(1)), int(match.group(2)), None,
                               None)
    elif components == 3 and not allowPrerelease:
        return SemanticVersion(int(match.group(1)), int(match.group(2)),
                               int(match.group(3)), None)
    elif components == 3 and allowPrerelease:
        return SemanticVersion(int(match.group(1)), int(match.group(2)),
                               int(match.group(3)), match.group('prerelease'))
    else:
        raise Exception('Argument "components" must be 2 or 3')
