# Copyright 2022 The ANGLE Project Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import contextlib
import functools
import glob
import hashlib
import json
import logging
import os
import pathlib
import platform
import posixpath
import random
import re
import subprocess
import sys
import tarfile
import tempfile
import threading
import time
import zipfile

import angle_path_util


ANGLE_TRACE_TEST_SUITE = 'angle_trace_tests'


class _Global(object):
    initialized = False
    is_android = False
    current_suite = None
    current_user = None
    external_storage = None
    has_adb_root = False
    traces_outside_of_apk = False
    base_dir = None
    temp_dir = None
    use_run_as = True

    @classmethod
    def IsMultiUser(cls):
        assert cls.current_user != None, "Call _GetCurrentUser before using IsMultiUser"
        return cls.current_user != '0'

def _ApkPath(suite_name):
    return os.path.join('%s_apk' % suite_name, '%s-debug.apk' % suite_name)


def _RemovePrefix(str, prefix):
    assert str.startswith(prefix), 'Expected prefix %s, got: %s' % (prefix, str)
    return str[len(prefix):]


def _InitializeAndroid(apk_path):
    # Pull a few pieces of data with a single adb trip
    shell_id, su_path, current_user, data_permissions = _AdbShell(
        'id -u; which su || echo noroot; am get-current-user; stat --format %a /data').decode(
        ).strip().split('\n')

    # Populate globals with those results
    _Global.has_adb_root = _GetAdbRoot(shell_id, su_path)
    _Global.current_user = _GetCurrentUser(current_user)
    _Global.use_run_as = _GetRunAs(data_permissions)

    # Storage location varies by user
    _Global.external_storage = '/storage/emulated/' + _Global.current_user + '/chromium_tests_root/'

    # We use the app's home directory for storing several things
    _Global.base_dir = '/data/user/' + _Global.current_user + '/com.android.angle.test/'

    if _Global.has_adb_root:
        # /data/local/tmp/ is not writable by apps.. So use the app path
        _Global.temp_dir = _Global.base_dir + 'tmp/'
        # Additionally, if we're not the default user, we need to use the app's dir for external storage
        if _Global.IsMultiUser():
            # TODO(b/361388557): Switch to a content provider for this, i.e. `content write`
            logging.warning(
                '\n\n!!!!! Using app dir for external storage, may not work with chromium scripts, may require `setenforce 0` !!!!!\n'
            )
            _Global.external_storage = _Global.base_dir + 'chromium_tests_root/'
    else:
        # /sdcard/ is slow (see https://crrev.com/c/3615081 for details)
        # logging will be fully-buffered, can be truncated on crashes
        _Global.temp_dir = '/storage/emulated/' + _Global.current_user + '/'

    logging.debug('Temp dir: %s', _Global.temp_dir)
    logging.debug('External storage: %s', _Global.external_storage)

    with zipfile.ZipFile(apk_path) as zf:
        apk_so_libs = [posixpath.basename(f) for f in zf.namelist() if f.endswith('.so')]

    # When traces are outside of the apk this lib is also outside
    interpreter_so_lib = 'libangle_trace_interpreter.so'
    _Global.traces_outside_of_apk = interpreter_so_lib not in apk_so_libs

    if logging.getLogger().isEnabledFor(logging.DEBUG):
        logging.debug(_AdbShell('df -h').decode())


def Initialize(suite_name):
    if _Global.initialized:
        return

    apk_path = _ApkPath(suite_name)
    if os.path.exists(apk_path):
        _Global.is_android = True
        _InitializeAndroid(apk_path)

    _Global.initialized = True


def IsAndroid():
    assert _Global.initialized, 'Initialize not called'
    return _Global.is_android


def _EnsureTestSuite(suite_name):
    assert IsAndroid()

    if _Global.current_suite != suite_name:
        PrepareTestSuite(suite_name)
        _Global.current_suite = suite_name


def _Run(cmd):
    logging.debug('Executing command: %s', cmd)
    startupinfo = None
    if hasattr(subprocess, 'STARTUPINFO'):
        # Prevent console window popping up on Windows
        startupinfo = subprocess.STARTUPINFO()
        startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
        startupinfo.wShowWindow = subprocess.SW_HIDE
    output = subprocess.check_output(cmd, startupinfo=startupinfo)
    return output


@functools.lru_cache()
def FindAdb():
    if platform.system() == 'Windows':
        adb = 'adb.exe'  # from PATH
    else:
        platform_tools = (
            pathlib.Path(angle_path_util.ANGLE_ROOT_DIR) / 'third_party' / 'android_sdk' /
            'public' / 'platform-tools')
        adb = str(platform_tools / 'adb') if platform_tools.exists() else 'adb'

    adb_info = ', '.join(subprocess.check_output([adb, '--version']).decode().strip().split('\n'))
    logging.info('adb --version: %s', adb_info)
    return adb


def _AdbRun(args):
    return _Run([FindAdb()] + args)


def _AdbShell(cmd):
    output = _Run([FindAdb(), 'shell', cmd])
    if platform.system() == 'Windows':
        return output.replace(b'\r\n', b'\n')
    return output


def _AdbShellWithRunAs(cmd):
    if _Global.use_run_as:
        cmd = "run-as com.android.angle.test sh -c '{cmd}'".format(cmd=cmd)
    return _AdbShell(cmd)


def _GetAdbRoot(shell_id, su_path):
    if int(shell_id) == 0:
        logging.info('adb already got root')
        return True

    if su_path == 'noroot':
        logging.warning('adb root not available on this device')
        return False

    logging.info('Getting adb root (may take a few seconds)')
    _AdbRun(['root'])
    for _ in range(20):  # `adb root` restarts adbd which can take quite a few seconds
        time.sleep(0.5)
        id_out = _AdbShell('id -u').decode('ascii').strip()
        if id_out == '0':
            logging.info('adb root succeeded')
            return True

    # Device has "su" but we couldn't get adb root. Something is wrong.
    raise Exception('Failed to get adb root')


def _GetRunAs(data_permissions):
    # Determine run-as usage
    if data_permissions.endswith('7'):
        # run-as broken due to "/data readable or writable by others"
        logging.warning('run-as not available due to /data permissions')
        return False

    if _Global.IsMultiUser():
        # run-as is failing is the presence of multiple users
        logging.warning('Disabling run-as for non-default user')
        return False

    return True


def _GetCurrentUser(current_user):
    # Ensure current user is clean
    assert current_user.isnumeric(), current_user
    logging.debug('Current user: %s', current_user)
    return current_user


def _ReadDeviceFile(device_path):
    with _TempLocalFile() as tempfile_path:
        _AdbRun(['pull', device_path, tempfile_path])
        with open(tempfile_path, 'rb') as f:
            return f.read()


def _RemoveDeviceFile(device_path):
    _AdbShell('rm -f ' + device_path + ' || true')  # ignore errors


def _MakeTar(path, patterns):
    with _TempLocalFile() as tempfile_path:
        with tarfile.open(tempfile_path, 'w', format=tarfile.GNU_FORMAT) as tar:
            for p in patterns:
                for f in glob.glob(p, recursive=True):
                    tar.add(f, arcname=f.replace('../../', ''))
        _AdbRun(['push', tempfile_path, path])


def _AddRestrictedTracesJson():
    _MakeTar(_Global.external_storage + 't.tar', [
        '../../src/tests/restricted_traces/*/*.json',
        'gen/trace_list.json',
    ])
    _AdbShell(
        'r=' + _Global.external_storage +
        '; tar --no-same-permissions --no-same-owner -xf $r/t.tar -C $r/ && rm $r/t.tar && chmod -R o+r $r/'
    )


def _AddDeqpFiles(suite_name):
    patterns = [
        '../../third_party/VK-GL-CTS/src/external/openglcts/data/gl_cts/data/mustpass/*/*/main/*.txt',
        '../../src/tests/deqp_support/*.txt'
    ]
    if '_gles2_' in suite_name:
        patterns.append('gen/vk_gl_cts_data/data/gles2/**')
    elif '_gles3_' in suite_name:
        patterns.append('gen/vk_gl_cts_data/data/gles3/**')
        patterns.append('gen/vk_gl_cts_data/data/gl_cts/data/gles3/**')
    elif '_gles31_' in suite_name:
        patterns.append('gen/vk_gl_cts_data/data/gles31/**')
        patterns.append('gen/vk_gl_cts_data/data/gl_cts/data/gles31/**')
    elif '_gles32_' in suite_name:
        patterns.append('gen/vk_gl_cts_data/data/gl_cts/data/gles32/**')
    else:
        # Harness crashes if vk_gl_cts_data/data dir doesn't exist, so add a file
        patterns.append('gen/vk_gl_cts_data/data/gles2/data/brick.png')

    _MakeTar(_Global.external_storage + 'deqp.tar', patterns)
    _AdbShell(
        'r=' + _Global.external_storage +
        '; tar --no-same-permissions --no-same-owner -xf $r/deqp.tar -C $r/ && rm $r/deqp.tar && chmod -R o+r $r/'
    )


def _GetDeviceApkPath():
    pm_path = _AdbShell('pm path com.android.angle.test || true').decode().strip()
    if not pm_path:
        logging.debug('No installed path found for com.android.angle.test')
        return None
    device_apk_path = _RemovePrefix(pm_path, 'package:')
    logging.debug('Device APK path is %s' % device_apk_path)
    return device_apk_path


def _LocalFileHash(local_path, gz_tail_size):
    h = hashlib.sha256()
    with open(local_path, 'rb') as f:
        if local_path.endswith('.gz'):
            # equivalent of tail -c {gz_tail_size}
            offset = os.path.getsize(local_path) - gz_tail_size
            if offset > 0:
                f.seek(offset)
        for data in iter(lambda: f.read(65536), b''):
            h.update(data)
    return h.hexdigest()


def _CompareHashes(local_path, device_path):
    # The last 8 bytes of gzip contain CRC-32 and the initial file size and the preceding
    # bytes should be affected by changes in the middle if we happen to run into a collision
    gz_tail_size = 4096

    if local_path.endswith('.gz'):
        cmd = 'test -f {path} && tail -c {gz_tail_size} {path} | sha256sum -b || true'.format(
            path=device_path, gz_tail_size=gz_tail_size)
    else:
        cmd = 'test -f {path} && sha256sum -b {path} || true'.format(path=device_path)

    if _Global.use_run_as and device_path.startswith('/data'):
        # Use run-as for files that reside on /data, which aren't accessible without root
        cmd = "run-as com.android.angle.test sh -c '{cmd}'".format(cmd=cmd)

    device_hash = _AdbShell(cmd).decode().strip()
    if not device_hash:
        logging.debug('_CompareHashes: File not found on device')
        return False  # file not on device

    return _LocalFileHash(local_path, gz_tail_size) == device_hash


def _CheckSameApkInstalled(apk_path):
    device_apk_path = _GetDeviceApkPath()

    try:
        if device_apk_path and _CompareHashes(apk_path, device_apk_path):
            return True
    except subprocess.CalledProcessError as e:
        # non-debuggable test apk installed on device breaks run-as
        logging.warning('_CompareHashes of apk failed: %s' % e)

    return False


def PrepareTestSuite(suite_name):
    apk_path = _ApkPath(suite_name)

    if _CheckSameApkInstalled(apk_path):
        logging.info('Skipping APK install because host and device hashes match')
    else:
        logging.info('Installing apk path=%s size=%s' % (apk_path, os.path.getsize(apk_path)))
        _AdbRun(['install', '-r', '-d', apk_path])

    permissions = [
        'android.permission.CAMERA', 'android.permission.CHANGE_CONFIGURATION',
        'android.permission.READ_EXTERNAL_STORAGE', 'android.permission.RECORD_AUDIO',
        'android.permission.WRITE_EXTERNAL_STORAGE'
    ]
    _AdbShell('for q in %s;do pm grant com.android.angle.test "$q";done;' %
              (' '.join(permissions)))

    _AdbShell('appops set com.android.angle.test MANAGE_EXTERNAL_STORAGE allow || true')

    _AdbShell('mkdir -p ' + _Global.external_storage)
    _AdbShell('mkdir -p %s' % _Global.temp_dir)

    if suite_name == ANGLE_TRACE_TEST_SUITE:
        _AddRestrictedTracesJson()
        _AdbRun([
            'push', '../../src/tests/perf_tests/angle_trace_tests_expectations.txt',
            _Global.external_storage + 'src/tests/perf_tests/angle_trace_tests_expectations.txt'
        ])

    if '_deqp_' in suite_name:
        _AddDeqpFiles(suite_name)

    if suite_name == 'angle_end2end_tests':
        _AdbRun([
            'push', '../../src/tests/angle_end2end_tests_expectations.txt',
            _Global.external_storage + 'src/tests/angle_end2end_tests_expectations.txt'
        ])


def PrepareRestrictedTraces(traces):
    start = time.time()
    total_size = 0
    skipped = 0

    # In order to get files to the app's home directory and loadable as libraries, we must first
    # push them to tmp on the device.  We then use `run-as` which allows copying files from tmp.
    # Note that `mv` is not allowed with `run-as`.  This means there will briefly be two copies
    # of the trace on the device, so keep that in mind as space becomes a problem in the future.
    app_tmp_path = '/data/local/tmp/angle_traces/'

    if _Global.use_run_as:
        _AdbShell('mkdir -p ' + app_tmp_path +
                  ' && run-as com.android.angle.test mkdir -p angle_traces')
    else:
        _AdbShell('mkdir -p ' + app_tmp_path + ' ' + _Global.base_dir + 'angle_traces/')

    def _HashesMatch(local_path, device_path):
        nonlocal total_size, skipped
        if _CompareHashes(local_path, device_path):
            skipped += 1
            return True
        else:
            total_size += os.path.getsize(local_path)
            return False

    def _Push(local_path, path_from_root):
        device_path = _Global.external_storage + path_from_root
        if not _HashesMatch(local_path, device_path):
            _AdbRun(['push', local_path, device_path])

    def _PushLibToAppDir(lib_name):
        local_path = lib_name
        if not os.path.exists(local_path):
            print('Error: missing library: ' + local_path)
            print('Is angle_restricted_traces set in gn args?')  # b/294861737
            sys.exit(1)

        device_path = _Global.base_dir + 'angle_traces/' + lib_name
        if _HashesMatch(local_path, device_path):
            return

        if _Global.use_run_as:
            tmp_path = posixpath.join(app_tmp_path, lib_name)
            logging.debug('_PushToAppDir: Pushing %s to %s' % (local_path, tmp_path))
            try:
                _AdbRun(['push', local_path, tmp_path])
                _AdbShell('run-as com.android.angle.test cp ' + tmp_path + ' ./angle_traces/')
                _AdbShell('rm ' + tmp_path)
            finally:
                _RemoveDeviceFile(tmp_path)
        else:
            _AdbRun(['push', local_path, _Global.base_dir + 'angle_traces/'])

    # Set up each trace
    for idx, trace in enumerate(sorted(traces)):
        logging.info('Syncing %s trace (%d/%d)', trace, idx + 1, len(traces))

        path_from_root = 'src/tests/restricted_traces/' + trace + '/' + trace + '.angledata.gz'
        # If compressed binary data file does not exist use correct uncompressed filename
        if not os.path.exists('../../' + path_from_root):
            path_from_root = 'src/tests/restricted_traces/' + trace + '/' + trace + '.angledata'
        _Push('../../' + path_from_root, path_from_root)

        if _Global.traces_outside_of_apk:
            lib_name = 'libangle_restricted_traces_' + trace + '.so'
            _PushLibToAppDir(lib_name)

        tracegz = 'gen/tracegz_' + trace + '.gz'
        if os.path.exists(tracegz):  # Requires angle_enable_tracegz
            _Push(tracegz, tracegz)

    # Push one additional file when running outside the APK
    if _Global.traces_outside_of_apk:
        _PushLibToAppDir('libangle_trace_interpreter.so')

    logging.info('Synced files for %d traces (%.1fMB, %d files already ok) in %.1fs', len(traces),
                 total_size / 1e6, skipped,
                 time.time() - start)


def _RandomHex():
    return hex(random.randint(0, 2**64))[2:]


@contextlib.contextmanager
def _TempDeviceDir():
    path = posixpath.join(_Global.temp_dir, 'temp_dir-%s' % _RandomHex())
    _AdbShell('mkdir -p ' + path)
    try:
        yield path
    finally:
        _AdbShell('rm -rf ' + path)


@contextlib.contextmanager
def _TempDeviceFile():
    path = posixpath.join(_Global.temp_dir, 'temp_file-%s' % _RandomHex())
    try:
        yield path
    finally:
        _AdbShell('rm -f ' + path)


@contextlib.contextmanager
def _TempLocalFile():
    fd, path = tempfile.mkstemp()
    os.close(fd)
    try:
        yield path
    finally:
        os.remove(path)


def _SetCaptureProps(env, device_out_dir):
    capture_var_map = {  # src/libANGLE/capture/FrameCapture.cpp
        'ANGLE_CAPTURE_ENABLED': 'debug.angle.capture.enabled',
        'ANGLE_CAPTURE_FRAME_START': 'debug.angle.capture.frame_start',
        'ANGLE_CAPTURE_FRAME_END': 'debug.angle.capture.frame_end',
        'ANGLE_CAPTURE_MAX_RESIDENT_BINARY_SIZE': 'debug.angle.capture.max_resident_binary_size',
        'ANGLE_CAPTURE_BLOCK_SIZE': 'debug.angle.capture.block_size',
        'ANGLE_CAPTURE_TRIGGER': 'debug.angle.capture.trigger',
        'ANGLE_CAPTURE_END_CAPTURE': 'debug.angle.capture.end_capture',
        'ANGLE_CAPTURE_LABEL': 'debug.angle.capture.label',
        'ANGLE_CAPTURE_COMPRESSION': 'debug.angle.capture.compression',
        'ANGLE_CAPTURE_VALIDATION': 'debug.angle.capture.validation',
        'ANGLE_CAPTURE_VALIDATION_EXPR': 'debug.angle.capture.validation_expr',
        'ANGLE_CAPTURE_SOURCE_EXT': 'debug.angle.capture.source_ext',
        'ANGLE_CAPTURE_SOURCE_SIZE': 'debug.angle.capture.source_size',
        'ANGLE_CAPTURE_FORCE_SHADOW': 'debug.angle.capture.force_shadow',
    }
    empty_value = '""'
    shell_cmds = [
        # out_dir is special because the corresponding env var is a host path not a device path
        'setprop debug.angle.capture.out_dir ' + (device_out_dir or empty_value),
    ] + [
        'setprop %s %s' % (v, env.get(k, empty_value)) for k, v in sorted(capture_var_map.items())
    ]

    _AdbShell('\n'.join(shell_cmds))


def _RunInstrumentation(flags):
    with _TempDeviceFile() as temp_device_file:
        cmd = r'''
am instrument --user {user} -w \
    -e org.chromium.native_test.NativeTestInstrumentationTestRunner.StdoutFile {out} \
    -e org.chromium.native_test.NativeTest.CommandLineFlags "{flags}" \
    -e org.chromium.native_test.NativeTestInstrumentationTestRunner.ShardNanoTimeout "1000000000000000000" \
    -e org.chromium.native_test.NativeTestInstrumentationTestRunner.NativeTestActivity \
    com.android.angle.test.AngleUnitTestActivity \
    com.android.angle.test/org.chromium.build.gtest_apk.NativeTestInstrumentationTestRunner
        '''.format(
            user=_Global.current_user, out=temp_device_file, flags=r' '.join(flags)).strip()

        capture_out_dir = os.environ.get('ANGLE_CAPTURE_OUT_DIR')
        if capture_out_dir:
            assert os.path.isdir(capture_out_dir)
            with _TempDeviceDir() as device_out_dir:
                _SetCaptureProps(os.environ, device_out_dir)
                try:
                    _AdbShell(cmd)
                finally:
                    _SetCaptureProps({}, None)  # reset
                _PullDir(device_out_dir, capture_out_dir)
        else:
            _AdbShell(cmd)
        return _ReadDeviceFile(temp_device_file)


def AngleSystemInfo(args):
    _EnsureTestSuite('angle_system_info_test')

    with _TempDeviceDir() as temp_dir:
        _RunInstrumentation(args + ['--render-test-output-dir=' + temp_dir])
        output_file = posixpath.join(temp_dir, 'angle_system_info.json')
        return json.loads(_ReadDeviceFile(output_file))


def GetBuildFingerprint():
    return _AdbShell('getprop ro.build.fingerprint').decode('ascii').strip()


def _PullDir(device_dir, local_dir):
    files = _AdbShell('ls -1 %s' % device_dir).decode('ascii').split('\n')
    for f in files:
        f = f.strip()
        if f:
            _AdbRun(['pull', posixpath.join(device_dir, f), posixpath.join(local_dir, f)])


def _RemoveFlag(args, f):
    matches = [a for a in args if a.startswith(f + '=')]
    assert len(matches) <= 1
    if matches:
        original_value = matches[0].split('=')[1]
        args.remove(matches[0])
    else:
        original_value = None

    return original_value


def RunTests(test_suite, args, stdoutfile=None, log_output=True):
    _EnsureTestSuite(test_suite)

    args = args[:]
    test_output_path = _RemoveFlag(args, '--isolated-script-test-output')
    perf_output_path = _RemoveFlag(args, '--isolated-script-test-perf-output')
    test_output_dir = _RemoveFlag(args, '--render-test-output-dir')

    result = 0
    output = b''
    output_json = {}
    try:
        with contextlib.ExitStack() as stack:
            device_test_output_path = stack.enter_context(_TempDeviceFile())
            args.append('--isolated-script-test-output=' + device_test_output_path)

            if perf_output_path:
                device_perf_path = stack.enter_context(_TempDeviceFile())
                args.append('--isolated-script-test-perf-output=%s' % device_perf_path)

            if test_output_dir:
                assert os.path.isdir(test_output_dir), 'Dir does not exist: %s' % test_output_dir
                device_output_dir = stack.enter_context(_TempDeviceDir())
                args.append('--render-test-output-dir=' + device_output_dir)

            output = _RunInstrumentation(args)

            if '--list-tests' in args:
                # When listing tests, there may be no output file. We parse stdout anyways.
                test_output = b'{"interrupted": false}'
            else:
                try:
                    test_output = _ReadDeviceFile(device_test_output_path)
                except subprocess.CalledProcessError:
                    logging.error('Unable to read test json output. Stdout:\n%s', output.decode())
                    result = 1
                    return result, output.decode(), None

            if test_output_path:
                with open(test_output_path, 'wb') as f:
                    f.write(test_output)

            output_json = json.loads(test_output)

            num_failures = output_json.get('num_failures_by_type', {}).get('FAIL', 0)
            interrupted = output_json.get('interrupted', True)  # Normally set to False
            if num_failures != 0 or interrupted or output_json.get('is_unexpected', False):
                logging.error('Tests failed: %s', test_output.decode())
                result = 1

            if test_output_dir:
                _PullDir(device_output_dir, test_output_dir)

            if perf_output_path:
                _AdbRun(['pull', device_perf_path, perf_output_path])

        if log_output or result:
            logging.info(output.decode())

        if result:
            logging.error('Tests failed, see stdout above')

        if stdoutfile:
            with open(stdoutfile, 'wb') as f:
                f.write(output)
    except Exception as e:
        logging.exception(e)
        result = 1

    return result, output.decode(), output_json


def GetTraceFromTestName(test_name):
    if test_name.startswith('TraceTest.'):
        return test_name[len('TraceTest.'):]
    return None


def GetTemps():
    temps = _AdbShell(
        'cat /dev/thermal/tz-by-name/*_therm/temp 2>/dev/null || true').decode().split()
    logging.debug('tz-by-name temps: %s' % ','.join(temps))

    temps_celsius = []
    for t in temps:
        try:
            temps_celsius.append(float(t) / 1e3)
        except ValueError:
            pass

    return temps_celsius
