# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you 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 logging
import os
import re

try:
  from elftools.elf.elffile import ELFFile
except ImportError as e:
  # Handle pre-python2.7s' lack of collections.OrderedDict, which we include in
  # impala-python as ordereddict.OrderedDict.
  if 'cannot import name OrderedDict' == str(e):
    import monkeypatch
    from ordereddict import OrderedDict
    monkeypatch.patch(OrderedDict, 'collections', 'OrderedDict')
    from elftools.elf.elffile import ELFFile
  else:
    raise e


LOG = logging.getLogger('tests.common.environ')


test_start_cluster_args = os.environ.get("TEST_START_CLUSTER_ARGS", "")

# Find the likely BuildType of the running Impala. Assume it's found through the path
# $IMPALA_HOME/be/build/latest as a fallback.
impala_home = os.environ.get("IMPALA_HOME", "")
build_type_arg_regex = re.compile(r'--build_type=(\w+)', re.I)
build_type_arg_search_result = re.search(build_type_arg_regex, test_start_cluster_args)

if build_type_arg_search_result is not None:
  build_type_dir = build_type_search_result.groups()[0].lower()
else:
  build_type_dir = 'latest'

# Resolve any symlinks in the path.
impalad_basedir = \
    os.path.realpath(os.path.join(impala_home, 'be/build', build_type_dir)).rstrip('/')

IMPALAD_PATH = os.path.join(impalad_basedir, 'service', 'impalad')


class SpecificImpaladBuildTypes:
  """
  Represent a specific build type. In reality, there 5 specific build types. These
  specific build types are needed by Python test code.

  The specific build types and their *most distinguishing* compiler options are:

  1. ADDRESS_SANITIZER (clang -fsanitize=address)
  2. DEBUG (gcc -ggdb)
  3. DEBUG_CODE_COVERAGE (gcc -ggdb -ftest-coverage)
  4. RELEASE (gcc)
  5. RELEASE_CODE_COVERAGE (gcc -ftest-coverage)
  """
  # ./buildall.sh -asan
  ADDRESS_SANITIZER = 'address_sanitizer'
  # ./buildall.sh
  DEBUG = 'debug'
  # ./buildall.sh -codecoverage
  DEBUG_CODE_COVERAGE = 'debug_code_coverage'
  # ./buildall.sh -release
  RELEASE = 'release'
  # ./buildall.sh -release -codecoverage
  RELEASE_CODE_COVERAGE = 'release_code_coverage'


class ImpaladBuild(object):
  """
  Acquires and provides characteristics about the way the Impala under test was compiled
  and its likely effects on its responsiveness to automated test timings.
  """
  def __init__(self, impalad_path):
    self.impalad_path = impalad_path
    die_name, die_producer = self._get_impalad_dwarf_info()
    self._set_impalad_build_type(die_name, die_producer)

  @property
  def specific_build_type(self):
    """
    Return the correct SpecificImpaladBuildTypes for the Impala under test.
    """
    return self._specific_build_type

  def has_code_coverage(self):
    """
    Return whether the Impala under test was compiled with code coverage enabled.
    """
    return self.specific_build_type in (SpecificImpaladBuildTypes.DEBUG_CODE_COVERAGE,
                                        SpecificImpaladBuildTypes.RELEASE_CODE_COVERAGE)

  def is_asan(self):
    """
    Return whether the Impala under test was compiled with ASAN.
    """
    return self.specific_build_type == SpecificImpaladBuildTypes.ADDRESS_SANITIZER

  def is_dev(self):
    """
    Return whether the Impala under test is a development build (i.e., any debug or ASAN
    build).
    """
    return self.specific_build_type in (
        SpecificImpaladBuildTypes.ADDRESS_SANITIZER, SpecificImpaladBuildTypes.DEBUG,
        SpecificImpaladBuildTypes.DEBUG_CODE_COVERAGE)

  def runs_slowly(self):
    """
    Return whether the Impala under test "runs slowly". For our purposes this means
    either compiled with code coverage enabled or ASAN.
    """
    return self.has_code_coverage() or self.is_asan()

  def _get_impalad_dwarf_info(self):
    """
    Read the impalad_path ELF binary, which is supposed to contain DWARF, and read the
    DWARF to understand the compiler options. Return a 2-tuple of the two useful DIE
    attributes of the first compile unit: the DW_AT_name and DW_AT_producer. If
    something goes wrong doing this, log a warning and return nothing.
    """
    # Some useful references:
    # - be/CMakeLists.txt
    # - gcc(1), especially -grecord-gcc-switches, -g, -ggdb, -gdwarf-2
    # - readelf(1)
    # - general reading about DWARF
    # A useful command for exploration without having to wade through many bytes is:
    # readelf --debug-dump=info --dwarf-depth=1 impalad
    # The DWARF lines are long, raw, and nasty; I'm hesitant to paste them here, so
    # curious readers are highly encouraged to try the above, or read IMPALA-3501.
    die_name = None
    die_producer = None
    try:
      with open(self.impalad_path, 'rb') as fh:
        impalad_elf = ELFFile(fh)
        if impalad_elf.has_dwarf_info():
          dwarf_info = impalad_elf.get_dwarf_info()
          # We only need the first CU, hence the unconventional use of the iterator
          # protocol.
          cu_iterator = dwarf_info.iter_CUs()
          first_cu = next(cu_iterator)
          top_die = first_cu.get_top_DIE()
          die_name = top_die.attributes['DW_AT_name'].value
          die_producer = top_die.attributes['DW_AT_producer'].value
    except Exception as e:
      LOG.warn('Failure to read DWARF info from {0}: {1}'.format(self.impalad_path,
                                                                 str(e)))
    return die_name, die_producer

  def _set_impalad_build_type(self, die_name, die_producer):
    """
    Use a heuristic based on the DW_AT_producer and DW_AT_name of the first compile
    unit, as returned by _get_impalad_dwarf_info(), to figure out which of 5 supported
    builds of impalad we're dealing with. If the heuristic can't determine, fall back to
    assuming a debug build and log a warning.
    """
    ASAN_CU_NAME = 'asan_preinit.cc'
    NON_ASAN_CU_NAME = 'daemon-main.cc'
    GDB_FLAG = '-ggdb'
    CODE_COVERAGE_FLAG = '-ftest-coverage'

    if die_name is None or die_producer is None:
      LOG.warn('Not enough DWARF info in {0} to determine build type; choosing '
               'DEBUG'.format(self.impalad_path))
      self._specific_build_type = SpecificImpaladBuildTypes.DEBUG
      return

    is_debug = GDB_FLAG in die_producer
    specific_build_type = SpecificImpaladBuildTypes.DEBUG

    if die_name.endswith(ASAN_CU_NAME):
      specific_build_type = SpecificImpaladBuildTypes.ADDRESS_SANITIZER
    elif not die_name.endswith(NON_ASAN_CU_NAME):
      LOG.warn('Unexpected DW_AT_name in first CU: {0}; choosing '
               'DEBUG'.format(die_name))
      specific_build_type = SpecificImpaladBuildTypes.DEBUG
    elif CODE_COVERAGE_FLAG in die_producer:
      if is_debug:
        specific_build_type = SpecificImpaladBuildTypes.DEBUG_CODE_COVERAGE
      else:
        specific_build_type = SpecificImpaladBuildTypes.RELEASE_CODE_COVERAGE
    else:
      if is_debug:
        specific_build_type = SpecificImpaladBuildTypes.DEBUG
      else:
        specific_build_type = SpecificImpaladBuildTypes.RELEASE

    self._specific_build_type = specific_build_type


IMPALAD_BUILD = ImpaladBuild(IMPALAD_PATH)


def specific_build_type_timeout(
    default_timeout, slow_build_timeout=None, asan_build_timeout=None,
    code_coverage_build_timeout=None):
  """
  Return a test environment-specific timeout based on the sort of
  SpecificImpalaBuildType under test.

  Required parameter: default_timeout - default timeout value. This applies when Impala is
  a standard release or debug build, or if no other timeouts are specified.

  Optional parameters:
  slow_build_timeout - timeout to use if we're running against *any* build known to be
  slow. If specified, this will preempt default_timeout if Impala is expected to be
  "slow". You can use this as a shorthand in lieu of specifying all of the following
  parameters.

  The parameters below correspond to specific build types. These preempt both
  slow_build_timeout and default_timeout, if the Impala under test is a build of the
  applicable type:

  asan_build_timeout - timeout to use if Impala with ASAN is running

  code_coverage_build_timeout - timeout to use if Impala with code coverage is running
  (both debug and release code coverage)
  """

  if IMPALAD_BUILD.is_asan() and asan_build_timeout is not None:
    timeout_val = asan_build_timeout
  elif IMPALAD_BUILD.has_code_coverage() and code_coverage_build_timeout is not None:
    timeout_val = code_coverage_build_timeout
  elif IMPALAD_BUILD.runs_slowly() and slow_build_timeout is not None:
    timeout_val = slow_build_timeout
  else:
    timeout_val = default_timeout
  return timeout_val
