#!/usr/bin/env python3
# Copyright (C) 2017 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import argparse
import os
import functools
import logging
import subprocess
import sys
import time
""" Runs a test executable on Android.

Takes care of pushing the extra shared libraries that might be required by
some sanitizers. Propagates the test return code to the host, exiting with
0 only if the test execution succeeds on the device.
"""

ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
ADB_PATH = os.path.join(ROOT_DIR, 'buildtools/android_sdk/platform-tools/adb')


def RetryOn(exc_type=(), returns_falsy=False, retries=5):
  """Decorator to retry a function in case of errors or falsy values.

  Implements exponential backoff between retries.

  Args:
    exc_type: Type of exceptions to catch and retry on. May also pass a tuple
      of exceptions to catch and retry on any of them. Defaults to catching no
      exceptions at all.
    returns_falsy: If True then the function will be retried until it stops
      returning a "falsy" value (e.g. None, False, 0, [], etc.). If equal to
      'raise' and the function keeps returning falsy values after all retries,
      then the decorator will raise a ValueError.
    retries: Max number of retry attempts. After exhausting that number of
      attempts the function will be called with no safeguards: any exceptions
      will be raised and falsy values returned to the caller (except when
      returns_falsy='raise').
  """

  def Decorator(f):

    @functools.wraps(f)
    def Wrapper(*args, **kwargs):
      wait = 1
      this_retries = kwargs.pop('retries', retries)
      for _ in range(this_retries):
        retry_reason = None
        try:
          value = f(*args, **kwargs)
        except exc_type as exc:
          retry_reason = 'raised %s' % type(exc).__name__
        if retry_reason is None:
          if returns_falsy and not value:
            retry_reason = 'returned %r' % value
          else:
            return value  # Success!
        print('{} {}, will retry in {} second{} ...'.format(
            f.__name__, retry_reason, wait, '' if wait == 1 else 's'))
        time.sleep(wait)
        wait *= 2
      value = f(*args, **kwargs)  # Last try to run with no safeguards.
      if returns_falsy == 'raise' and not value:
        raise ValueError('%s returned %r' % (f.__name__, value))
      return value

    return Wrapper

  return Decorator


def AdbCall(*args):
  cmd = [ADB_PATH] + list(args)
  print('> adb ' + ' '.join(args))
  return subprocess.check_call(cmd)


def AdbPush(host, device):
  if not os.path.exists(host):
    logging.fatal('Cannot find %s. Was it built?', host)
  cmd = [ADB_PATH, 'push', host, device]
  print('> adb push ' + ' '.join(cmd[2:]))
  with open(os.devnull, 'wb') as devnull:
    return subprocess.check_call(cmd, stdout=devnull)


def GetProp(prop):
  cmd = [ADB_PATH, 'shell', 'getprop', prop]
  print('> adb ' + ' '.join(cmd))
  output = subprocess.check_output(cmd).decode()
  lines = output.splitlines()
  assert len(lines) == 1, 'Expected output to have one line: {}'.format(output)
  print(lines[0])
  return lines[0]


@RetryOn([subprocess.CalledProcessError], returns_falsy=True, retries=10)
def WaitForBootCompletion():
  return GetProp('sys.boot_completed') == '1'


def EnumerateDataDeps():
  with open(os.path.join(ROOT_DIR, 'tools', 'test_data.txt')) as f:
    lines = f.readlines()
  for line in (line.strip() for line in lines if not line.startswith('#')):
    assert os.path.exists(line), line
    yield line


def Main():
  parser = argparse.ArgumentParser()
  parser.add_argument('--no-cleanup', '-n', action='store_true')
  parser.add_argument('--no-data-deps', '-x', action='store_true')
  parser.add_argument('--system-adb', action='store_true')
  parser.add_argument('--env', '-e', action='append')
  parser.add_argument('out_dir', help='out/android/')
  parser.add_argument('test_name', help='perfetto_unittests')
  parser.add_argument('cmd_args', nargs=argparse.REMAINDER)
  args = parser.parse_args()

  if args.system_adb:
    global ADB_PATH
    ADB_PATH = 'adb'

  test_bin = os.path.join(args.out_dir, args.test_name)
  assert os.path.exists(test_bin)

  print('Waiting for device ...')
  AdbCall('wait-for-device')
  # WaitForBootCompletion()
  AdbCall('root')
  AdbCall('wait-for-device')

  target_dir = '/data/local/tmp/perfetto_tests'
  if not args.no_cleanup:
    AdbCall('shell', 'rm -rf "%s"' % target_dir)
  AdbCall('shell', 'mkdir -p "%s"' % target_dir)
  # Some tests require the trace directory to exist, while true for android
  # devices in general some emulators might not have it set up. So we check to
  # see if it exists, and if not create it.
  trace_dir = '/data/misc/perfetto-traces/bugreport'
  AdbCall('shell', 'test -d "%s" || mkdir -p "%s"' % (2 * (trace_dir,)))
  AdbCall('shell', 'rm -rf "%s/*";  ' % trace_dir)
  AdbCall('shell', 'mkdir -p /data/nativetest')
  AdbCall('shell', 'echo 0 > /d/tracing/tracing_on')

  # This needs to go into /data/nativetest in order to have the system linker
  # namespace applied, which we need in order to link libdexfile.so.
  # This gets linked into our tests via libundwindstack.so.
  #
  # See https://android.googlesource.com/platform/system/core/+/master/rootdir/etc/ld.config.txt.
  AdbPush(test_bin, "/data/nativetest")

  # These two binaries are required to run perfetto_integrationtests.
  AdbPush(os.path.join(args.out_dir, "perfetto"), "/data/nativetest")
  AdbPush(os.path.join(args.out_dir, "trigger_perfetto"), "/data/nativetest")

  if not args.no_data_deps:
    for dep in EnumerateDataDeps():
      AdbPush(os.path.join(ROOT_DIR, dep), target_dir + '/' + dep)

  # LLVM sanitizers require to sideload a libclangrtXX.so on the device.
  sanitizer_libs = os.path.join(args.out_dir, 'sanitizer_libs')
  env = ' '.join(args.env if args.env is not None else []) + ' '
  if os.path.exists(sanitizer_libs):
    AdbPush(sanitizer_libs, target_dir)
    env += 'LD_LIBRARY_PATH="%s/sanitizer_libs" ' % (target_dir)
  cmd = 'cd %s;' % target_dir
  binary = env + '/data/nativetest/%s' % args.test_name
  cmd += binary
  if args.cmd_args:
    actual_args = [arg.replace(args.test_name, binary) for arg in args.cmd_args]
    cmd += ' ' + ' '.join(actual_args)
  print(cmd)
  retcode = subprocess.call([ADB_PATH, 'shell', '-tt', cmd])
  if not args.no_cleanup:
    AdbCall('shell', 'rm -rf "%s"' % target_dir)

  # Smoke test that adb shell is actually propagating retcode. adb has a history
  # of breaking this.
  test_code = subprocess.call([ADB_PATH, 'shell', '-tt', 'echo Done; exit 42'])
  if test_code != 42:
    logging.fatal('adb is incorrectly propagating the exit code')
    return 1

  return retcode


if __name__ == '__main__':
  sys.exit(Main())
