# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""
Classes in this file define additional actions that need to be taken to run a
test under some kind of runtime error detection tool.

The interface is intended to be used as follows.

1. For tests that simply run a native process (i.e. no activity is spawned):

Call tool.CopyFiles().
Prepend test command line with tool.GetTestWrapper().

2. For tests that spawn an activity:

Call tool.CopyFiles().
Call tool.SetupEnvironment().
Run the test as usual.
Call tool.CleanUpEnvironment().
"""

import os.path
import sys

from constants import CHROME_DIR


def SetChromeTimeoutScale(adb, scale):
  """Sets the timeout scale in /data/local/tmp/chrome_timeout_scale to scale."""
  path = '/data/local/tmp/chrome_timeout_scale'
  if not scale or scale == 1.0:
    # Delete if scale is None/0.0/1.0 since the default timeout scale is 1.0
    adb.RunShellCommand('rm %s' % path)
  else:
    adb.SetFileContents(path, '%f' % scale)


class BaseTool(object):
  """A tool that does nothing."""

  def GetTestWrapper(self):
    """Returns a string that is to be prepended to the test command line."""
    return ''

  def GetUtilWrapper(self):
    """Returns the wrapper name for the utilities.

    Returns:
       A string that is to be prepended to the command line of utility
    processes (forwarder, etc.).
    """
    return ''

  def CopyFiles(self):
    """Copies tool-specific files to the device, create directories, etc."""
    pass

  def SetupEnvironment(self):
    """Sets up the system environment for a test.

    This is a good place to set system properties.
    """
    pass

  def CleanUpEnvironment(self):
    """Cleans up environment."""
    pass

  def GetTimeoutScale(self):
    """Returns a multiplier that should be applied to timeout values."""
    return 1.0

  def NeedsDebugInfo(self):
    """Whether this tool requires debug info.

    Returns:
      True if this tool can not work with stripped binaries.
    """
    return False


class AddressSanitizerTool(BaseTool):
  """AddressSanitizer tool."""

  TMP_DIR = '/data/local/tmp/asan'
  WRAPPER_NAME = 'asanwrapper.sh'

  def __init__(self, adb):
    self._adb = adb
    self._wrap_properties = ['wrap.com.google.android.apps.ch',
                             'wrap.org.chromium.native_test']

  def CopyFiles(self):
    """Copies ASan tools to the device."""
    files = ['tools/android/asan/asanwrapper.sh',
             'third_party/llvm-build/Release+Asserts/lib/clang/3.2/lib/linux/' +
                 'libclang_rt.asan-arm-android.so']
    for f in files:
      self._adb.PushIfNeeded(os.path.join(CHROME_DIR, f),
                             os.path.join(AddressSanitizerTool.TMP_DIR,
                                          os.path.basename(f)))

  def GetTestWrapper(self):
    return os.path.join(AddressSanitizerTool.TMP_DIR,
                        AddressSanitizerTool.WRAPPER_NAME)

  def GetUtilWrapper(self):
    """Returns the wrapper for utilities, such as forwarder.

    AddressSanitizer wrapper must be added to all instrumented binaries,
    including forwarder and the like. This can be removed if such binaries
    were built without instrumentation. """
    return self.GetTestWrapper()

  def SetupEnvironment(self):
    self._adb.EnableAdbRoot()
    for prop in self._wrap_properties:
      self._adb.RunShellCommand('setprop %s "logwrapper %s"' % (
          prop, self.GetTestWrapper()))
    SetChromeTimeoutScale(self._adb, self.GetTimeoutScale())

  def CleanUpEnvironment(self):
    for prop in self._wrap_properties:
      self._adb.RunShellCommand('setprop %s ""' % (prop,))
    SetChromeTimeoutScale(self._adb, None)

  def GetTimeoutScale(self):
    # Very slow startup.
    return 20.0


class ValgrindTool(BaseTool):
  """Base abstract class for Valgrind tools."""

  VG_DIR = '/data/local/tmp/valgrind'
  VGLOGS_DIR = '/data/local/tmp/vglogs'

  def __init__(self, adb):
    self._adb = adb
    # exactly 31 chars, SystemProperties::PROP_NAME_MAX
    self._wrap_properties = ['wrap.com.google.android.apps.ch',
                             'wrap.org.chromium.native_test']

  def CopyFiles(self):
    """Copies Valgrind tools to the device."""
    self._adb.RunShellCommand('rm -r %s; mkdir %s' %
                              (ValgrindTool.VG_DIR, ValgrindTool.VG_DIR))
    self._adb.RunShellCommand('rm -r %s; mkdir %s' %
                              (ValgrindTool.VGLOGS_DIR,
                               ValgrindTool.VGLOGS_DIR))
    files = self.GetFilesForTool()
    for f in files:
      self._adb.PushIfNeeded(os.path.join(CHROME_DIR, f),
                             os.path.join(ValgrindTool.VG_DIR,
                                          os.path.basename(f)))

  def SetupEnvironment(self):
    """Sets up device environment."""
    self._adb.RunShellCommand('chmod 777 /data/local/tmp')
    for prop in self._wrap_properties:
      self._adb.RunShellCommand('setprop %s "logwrapper %s"' % (
          prop, self.GetTestWrapper()))
    SetChromeTimeoutScale(self._adb, self.GetTimeoutScale())

  def CleanUpEnvironment(self):
    """Cleans up device environment."""
    for prop in self._wrap_properties:
      self._adb.RunShellCommand('setprop %s ""' % (prop,))
    SetChromeTimeoutScale(self._adb, None)

  def GetFilesForTool(self):
    """Returns a list of file names for the tool."""
    raise NotImplementedError()

  def NeedsDebugInfo(self):
    """Whether this tool requires debug info.

    Returns:
      True if this tool can not work with stripped binaries.
    """
    return True


class MemcheckTool(ValgrindTool):
  """Memcheck tool."""

  def __init__(self, adb):
    super(MemcheckTool, self).__init__(adb)

  def GetFilesForTool(self):
    """Returns a list of file names for the tool."""
    return ['tools/valgrind/android/vg-chrome-wrapper.sh',
            'tools/valgrind/memcheck/suppressions.txt',
            'tools/valgrind/memcheck/suppressions_android.txt']

  def GetTestWrapper(self):
    """Returns a string that is to be prepended to the test command line."""
    return ValgrindTool.VG_DIR + '/' + 'vg-chrome-wrapper.sh'

  def GetTimeoutScale(self):
    """Returns a multiplier that should be applied to timeout values."""
    return 30


class TSanTool(ValgrindTool):
  """ThreadSanitizer tool. See http://code.google.com/p/data-race-test ."""

  def __init__(self, adb):
    super(TSanTool, self).__init__(adb)

  def GetFilesForTool(self):
    """Returns a list of file names for the tool."""
    return ['tools/valgrind/android/vg-chrome-wrapper-tsan.sh',
            'tools/valgrind/tsan/suppressions.txt',
            'tools/valgrind/tsan/suppressions_android.txt',
            'tools/valgrind/tsan/ignores.txt']

  def GetTestWrapper(self):
    """Returns a string that is to be prepended to the test command line."""
    return ValgrindTool.VG_DIR + '/' + 'vg-chrome-wrapper-tsan.sh'

  def GetTimeoutScale(self):
    """Returns a multiplier that should be applied to timeout values."""
    return 30.0


TOOL_REGISTRY = {
    'memcheck': lambda x: MemcheckTool(x),
    'memcheck-renderer': lambda x: MemcheckTool(x),
    'tsan': lambda x: TSanTool(x),
    'tsan-renderer': lambda x: TSanTool(x),
    'asan': lambda x: AddressSanitizerTool(x),
}


def CreateTool(tool_name, adb):
  """Creates a tool with the specified tool name.

  Args:
    tool_name: Name of the tool to create.
    adb: ADB interface the tool will use.
  Returns:
    A tool for the specified tool_name.
  """
  if not tool_name:
    return BaseTool()

  ctor = TOOL_REGISTRY.get(tool_name)
  if ctor:
    return ctor(adb)
  else:
    print 'Unknown tool %s, available tools: %s' % (
        tool_name, ', '.join(sorted(TOOL_REGISTRY.keys())))
    sys.exit(1)
