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

"""Wrapper for tests that are run on builders."""

import fileinput
import optparse
import os
import re
import shutil
import sys
import urllib
import HTMLParser

import constants
sys.path.append(constants.SOURCE_ROOT)
import chromite.lib.cros_build_lib as cros_lib

_IMAGE_TO_EXTRACT = 'chromiumos_test_image.bin'
_NEW_STYLE_VERSION = '0.9.131.0'

class CrosImageDoesNotExistError(Exception):
  """Error thrown when no image can be found."""
  pass


class HTMLDirectoryParser(HTMLParser.HTMLParser):
  """HTMLParser for parsing the default apache file index."""

  def __init__(self, regex):
    HTMLParser.HTMLParser.__init__(self)
    self.regex_object = re.compile(regex)
    self.link_list = []

  def handle_starttag(self, tag, attrs):
    """Overrides from HTMLParser and is called at the start of every tag.

    This implementation grabs attributes from links (i.e. <a ... > </a>
    and adds the target from href=<target> if the <target> matches the
    regex given at the start.
    """
    if not tag.lower() == 'a':
      return

    for attr in attrs:
      if not attr[0].lower() == 'href':
        continue

      match = self.regex_object.match(attr[1])
      if match:
        self.link_list.append(match.group(0).rstrip('/'))


def ModifyBootDesc(download_folder, redirect_file=None):
  """Modifies the boot description of a downloaded image to work with path.

  The default boot.desc from another system is specific to the directory
  it was created in.  This modifies the boot description to be compatiable
  with the download folder.

  Args:
    download_folder: Absoulte path to the download folder.
    redirect_file:  For testing.  Where to copy new boot desc.
  """
  boot_desc_path = os.path.join(download_folder, 'boot.desc')
  in_chroot_folder = cros_lib.ReinterpretPathForChroot(download_folder)

  for line in fileinput.input(boot_desc_path, inplace=1):
    # Has to be done here to get changes to sys.stdout from fileinput.input.
    if not redirect_file:
      redirect_file = sys.stdout
    split_line = line.split('=')
    if len(split_line) > 1:
      var_part = split_line[0]
      potential_path = split_line[1].replace('"', '').strip()

      if potential_path.startswith('/home') and not 'output_dir' in var_part:
        new_path = os.path.join(in_chroot_folder,
                                os.path.basename(potential_path))
        new_line = '%s="%s"' % (var_part, new_path)
        cros_lib.Info('Replacing line %s with %s' % (line, new_line))
        redirect_file.write('%s\n' % new_line)
        continue
      elif 'output_dir' in var_part:
        # Special case for output_dir.
        new_line = '%s="%s"' % (var_part, in_chroot_folder)
        cros_lib.Info('Replacing line %s with %s' % (line, new_line))
        redirect_file.write('%s\n' % new_line)
        continue

    # Line does not need to be modified.
    redirect_file.write(line)

  fileinput.close()


def _GreaterVersion(version_a, version_b):
  """Returns the higher version number of two version number strings."""
  version_regex = re.compile('.*(\d+)\.(\d+)\.(\d+)\.(\d+).*')
  version_a_tokens = version_regex.match(version_a).groups()
  version_b_tokens = version_regex.match(version_b).groups()
  for i in range(4):
    (a, b) = (int(version_a_tokens[i]), int(version_b_tokens[i]))
    if a != b:
      if a > b: return version_a
      return version_b
  return version_a


def GetLatestLinkFromPage(url, regex):
  """Returns the latest link from the given url that matches regex.

  Args:
    url: Url to download and parse.
    regex: Regular expression to match links against.
  Raises:
    CrosImageDoesNotExistError if no image found using args.
  """
  url_file = urllib.urlopen(url)
  url_html = url_file.read()

  url_file.close()

  # Parses links with versions embedded.
  url_parser = HTMLDirectoryParser(regex=regex)
  url_parser.feed(url_html)
  try:
    return reduce(_GreaterVersion, url_parser.link_list)
  except TypeError:
    raise CrosImageDoesNotExistError('No image found at %s' % url)


def GetNewestLinkFromZipBase(board, channel, zip_server_base):
  """Returns the url to the newest image from the zip server.

  Args:
    board: board for the image zip.
    channel: channel for the image zip.
    zip_server_base:  base url for zipped images.
  Raises:
    CrosImageDoesNotExistError if no image found using args.
  """
  zip_base = os.path.join(zip_server_base, channel, board)
  latest_version = GetLatestLinkFromPage(zip_base, '\d+\.\d+\.\d+\.\d+/')

  zip_dir = os.path.join(zip_base, latest_version)
  zip_name = GetLatestLinkFromPage(zip_dir,
                                   'ChromeOS-\d+\.\d+\.\d+\.\d+-.*\.zip')
  return os.path.join(zip_dir, zip_name)


def GetLatestZipUrl(board, channel, zip_server_base):
  """Returns the url of the latest image zip for the given arguments.

  If the latest does not exist, tries to find the rc equivalent.  If neither
  exist, returns None.

  Args:
    board: board for the image zip.
    channel: channel for the image zip.
    zip_server_base:  base url for zipped images.
  """
  try:
    return GetNewestLinkFromZipBase(board, channel, zip_server_base)
  except CrosImageDoesNotExistError as ce:
    cros_lib.Warning(str(ce))
  try:
    return GetNewestLinkFromZipBase(board + '-rc', channel, zip_server_base)
  except CrosImageDoesNotExistError as ce:
    cros_lib.Warning(str(ce))
    return None


def GrabZipAndExtractImage(zip_url, download_folder, image_name) :
  """Downloads the zip and extracts the given image.

  Doesn't re-download if matching version found already in download folder.
  Args:
    zip_url - url for the image.
    download_folder - download folder to store zip file and extracted images.
    image_name - name of the image to extract from the zip file.
  """
  zip_path = os.path.join(download_folder, 'image.zip')
  versioned_url_path = os.path.join(download_folder, 'download_url')
  found_cached = False

  if os.path.exists(versioned_url_path):
    fh = open(versioned_url_path)
    version_url = fh.read()
    fh.close()

    if version_url == zip_url and os.path.exists(os.path.join(download_folder,
                                                 image_name)):
      cros_lib.Info('Using cached %s' % image_name)
      found_cached = True

  if not found_cached:
    cros_lib.Info('Downloading %s' % zip_url)
    cros_lib.RunCommand(['rm', '-rf', download_folder], print_cmd=False)
    os.mkdir(download_folder)
    urllib.urlretrieve(zip_url, zip_path)

    # Using unzip because python implemented unzip in native python so
    # extraction is really slow.
    cros_lib.Info('Unzipping image %s' % image_name)
    cros_lib.RunCommand(['unzip', '-d', download_folder, zip_path],
               print_cmd=False, error_message='Failed to download %s' % zip_url)

    ModifyBootDesc(download_folder)

    # Put url in version file so we don't have to do this every time.
    fh = open(versioned_url_path, 'w+')
    fh.write(zip_url)
    fh.close()

  version = zip_url.split('/')[-2]
  if not _GreaterVersion(version, _NEW_STYLE_VERSION) == version:
    # If the version isn't ready for new style, touch file to use old style.
    old_style_touch_path = os.path.join(download_folder, '.use_e1000')
    fh = open(old_style_touch_path, 'w+')
    fh.close()


def GeneratePublicKey(private_key_path):
  """Returns the path to a newly generated public key from given private key."""
  # Just output to local directory.
  public_key_path = 'public_key.pem'
  cros_lib.Info('Generating public key from private key.')
  cros_lib.RunCommand(['/usr/bin/openssl',
                       'rsa',
                       '-in', private_key_path,
                       '-pubout',
                       '-out', public_key_path,
                      ], print_cmd=False)
  return public_key_path



def RunAUTestHarness(board, channel, zip_server_base,
                     no_graphics, type, remote, clean, target_image,
                     test_results_root):
  """Runs the auto update test harness.

  The auto update test harness encapsulates testing the auto-update mechanism
  for the latest image against the latest official image from the channel.  This
  also tests images with suite_Smoke (built-in as part of its verification
  process).

  Args:
    board: the board for the latest image.
    channel: the channel to run the au test harness against.
    zip_server_base:  base url for zipped images.
    no_graphics: boolean - If True, disable graphics during vm test.
    type: which test harness to run.  Possible values: real, vm.
    remote: ip address for real test harness run.
    clean: Clean the state of test harness before running.
    target_image: Target image to test.
    test_results_root: Root directory to store au_test_harness results.
  """
  crosutils_root = os.path.join(constants.SOURCE_ROOT, 'src', 'scripts')

  if target_image is None:
    # Grab the latest image we've built.
    return_object = cros_lib.RunCommand(
      ['./get_latest_image.sh', '--board=%s' % board], cwd=crosutils_root,
      redirect_stdout=True, print_cmd=True)

    latest_image_dir = return_object.output.strip()
    target_image = os.path.join(latest_image_dir, _IMAGE_TO_EXTRACT)

  # Copy image to new directory.
  ctest_target_dir = os.path.abspath('ctest_target')
  if os.path.exists(ctest_target_dir):
    shutil.rmtree(ctest_target_dir)
  os.makedirs(ctest_target_dir)
  target_image_dir = os.path.dirname(target_image)
  new_target_image = os.path.join(ctest_target_dir, _IMAGE_TO_EXTRACT)
  for filename in os.listdir(target_image_dir):
    path = os.path.join(target_image_dir, filename)
    if (filename == _IMAGE_TO_EXTRACT or os.path.isfile(path) and
        'image' not in filename):
      cros_lib.Info('Copying %s to %s...' % (filename, ctest_target_dir))
      shutil.copy(path, ctest_target_dir)

  # Grab the latest official build for this board to use as the base image.
  # If it doesn't exist, run the update test against itself.
  download_folder = os.path.abspath('latest_download')
  zip_url = GetLatestZipUrl(board, channel, zip_server_base)

  base_image = None
  if zip_url:
    GrabZipAndExtractImage(zip_url, download_folder, _IMAGE_TO_EXTRACT)
    base_image = os.path.join(download_folder, _IMAGE_TO_EXTRACT)
  else:
    base_image = new_target_image

  update_engine_path = os.path.join(crosutils_root, '..', 'platform',
                                    'update_engine')

  if clean:
    private_key_path = os.path.join(update_engine_path, 'unittest_key.pem')
    public_key_path = GeneratePublicKey(private_key_path)

  cmd = ['bin/cros_au_test_harness',
         '--base_image=%s' % base_image,
         '--target_image=%s' % new_target_image,
         '--board=%s' % board,
         '--type=%s' % type,
         '--remote=%s' % remote,
         ]
  if test_results_root: cmd.append('--test_results_root=%s' % test_results_root)
  if no_graphics: cmd.append('--no_graphics')
  # Using keys is only compatible with clean.
  if clean:
    cmd.append('--clean')
    cmd.append('--private_key=%s' % private_key_path)
    cmd.append('--public_key=%s' % public_key_path)

  cros_lib.RunCommand(cmd, cwd=crosutils_root)


def main():
  parser = optparse.OptionParser()
  parser.add_option('-b', '--board',
                    help='board for the image to compare against.')
  parser.add_option('-c', '--channel',
                    help='channel for the image to compare against.')
  parser.add_option('--cache', default=False, action='store_true',
                    help='Cache payloads')
  parser.add_option('-z', '--zipbase',
                    help='Base url for hosted images.')
  parser.add_option('--no_graphics', action='store_true', default=False,
                    help='Disable graphics for the vm test.')
  parser.add_option('--target_image', default=None,
                    help='Target image to test.')
  parser.add_option('--test_results_root', default=None,
                    help='Root directory to store test results.  Should '
                         'be defined relative to chroot root.')
  parser.add_option('--type', default='vm',
                    help='type of test to run: [vm, real]. Default: vm.')
  parser.add_option('--remote', default='0.0.0.0',
                    help='For real tests, ip address of the target machine.')

  # Set the usage to include flags.
  parser.set_usage(parser.format_help())
  (options, args) = parser.parse_args()

  if args: parser.error('Extra args found %s.' % args)
  if not options.board: parser.error('Need board for image to compare against.')
  if not options.channel: parser.error('Need channel e.g. dev-channel.')
  if not options.zipbase: parser.error('Need zip url base to get images.')

  RunAUTestHarness(options.board, options.channel, options.zipbase,
                   options.no_graphics, options.type, options.remote,
                   not options.cache, options.target_image,
                   options.test_results_root)


if __name__ == '__main__':
  main()

