#!/usr/bin/env python
# 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 re
import functools
import logging
import subprocess
import sys
import tempfile
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 GetProp(prop):
  cmd = [ADB_PATH, 'shell', 'getprop', prop]
  print '> adb ' + ' '.join(cmd)
  output = subprocess.check_output(cmd)
  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('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()

  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/' + args.test_name
  AdbCall('shell', 'rm -rf "%s"; mkdir -p "%s"' % (2 * (target_dir,)))
  AdbCall('push', test_bin, target_dir)

  if not args.no_data_deps:
    for dep in EnumerateDataDeps():
      AdbCall('push', 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 = ''
  if os.path.exists(sanitizer_libs):
    AdbCall('push', sanitizer_libs, target_dir)
    env = 'LD_LIBRARY_PATH="%s/sanitizer_libs" ' % (target_dir)
  cmd = 'cd %s;' % target_dir;
  cmd += env + './%s' % args.test_name
  if args.cmd_args:
    cmd += ' ' + ' '.join(args.cmd_args)
  cmd += ';echo -e "\\nTEST_RET_CODE=$?"'
  print cmd
  test_output = subprocess.check_output([ADB_PATH, 'shell', cmd])
  print test_output
  retcode = re.search(r'^TEST_RET_CODE=(\d)', test_output, re.MULTILINE)
  assert retcode, 'Could not find TEST_RET_CODE=N marker'
  retcode = int(retcode.group(1))
  if not args.no_cleanup:
    AdbCall('shell', 'rm -rf "%s"' % target_dir)
  return retcode


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