#!/usr/bin/python

# Copyright (c) 2009 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.

''' Runs various chrome tests through heapcheck_test.py.

Most of this code is copied from ../valgrind/chrome_tests.py.
TODO(glider): put common functions to a standalone module.
'''

import glob
import logging
import optparse
import os
import stat
import sys

import google.logging_utils
import google.path_utils

# Import the platform_utils up in the layout tests which have been modified to
# work under non-Windows platforms instead of the ones that are in the
# tools/python/google directory. (See chrome_tests.sh which sets PYTHONPATH
# correctly.)
#
# TODO(erg): Copy/Move the relevant functions from the layout_package version
# of platform_utils back up to google.platform_utils
# package. http://crbug.com/6164
import layout_package.path_utils

import common
import heapcheck_test

class TestNotFound(Exception): pass

def Dir2IsNewer(dir1, dir2):
  if dir2 is None or not os.path.isdir(dir2):
    return False
  if dir1 is None or not os.path.isdir(dir1):
    return True
  return os.stat(dir2)[stat.ST_MTIME] > os.stat(dir1)[stat.ST_MTIME]

def FindNewestDir(dirs):
  newest_dir = None
  for dir in dirs:
    if Dir2IsNewer(newest_dir, dir):
      newest_dir = dir
  return newest_dir

def File2IsNewer(file1, file2):
  if file2 is None or not os.path.isfile(file2):
    return False
  if file1 is None or not os.path.isfile(file1):
    return True
  return os.stat(file2)[stat.ST_MTIME] > os.stat(file1)[stat.ST_MTIME]

def FindDirContainingNewestFile(dirs, file):
  """Searches for the directory containing the newest copy of |file|.

  Args:
    dirs: A list of paths to the directories to search among.
    file: A string containing the file name to search.

  Returns:
    The string representing the the directory containing the newest copy of
    |file|.

  Raises:
    IOError: |file| was not found.
  """
  newest_dir = None
  newest_file = None
  for dir in dirs:
    the_file = os.path.join(dir, file)
    if File2IsNewer(newest_file, the_file):
      newest_dir = dir
      newest_file = the_file
  if newest_dir is None:
    raise IOError("cannot find file %s anywhere, have you built it?" % file)
  return newest_dir

class ChromeTests(object):
  '''This class is derived from the chrome_tests.py file in ../purify/.
  '''

  def __init__(self, options, args, test):
    # The known list of tests.
    # Recognise the original abbreviations as well as full executable names.
    self._test_list = {
      "base": self.TestBase,            "base_unittests": self.TestBase,
      "browser": self.TestBrowser,      "browser_tests": self.TestBrowser,
      "googleurl": self.TestGURL,       "googleurl_unittests": self.TestGURL,
      "ipc": self.TestIpc,              "ipc_tests": self.TestIpc,
      "layout": self.TestLayout,        "layout_tests": self.TestLayout,
      "media": self.TestMedia,          "media_unittests": self.TestMedia,
      "net": self.TestNet,              "net_unittests": self.TestNet,
      "printing": self.TestPrinting,    "printing_unittests": self.TestPrinting,
      "startup": self.TestStartup,      "startup_tests": self.TestStartup,
      "test_shell": self.TestTestShell, "test_shell_tests": self.TestTestShell,
      "ui": self.TestUI,                "ui_tests": self.TestUI,
      "unit": self.TestUnit,            "unit_tests": self.TestUnit,
      "app": self.TestApp,              "app_unittests": self.TestApp,
    }

    if test not in self._test_list:
      raise TestNotFound("Unknown test: %s" % test)

    self._options = options
    self._args = args
    self._test = test

    script_dir = google.path_utils.ScriptDir()

    # Compute the top of the tree (the "source dir") from the script dir (where
    # this script lives).  We assume that the script dir is in tools/heapcheck/
    # relative to the top of the tree.
    self._source_dir = os.path.dirname(os.path.dirname(script_dir))

    # Since this path is used for string matching, make sure it's always
    # an absolute Windows-style path.
    self._source_dir = layout_package.path_utils.GetAbsolutePath(
        self._source_dir)
    heapcheck_test_script = os.path.join(script_dir, "heapcheck_test.py")
    self._command_preamble = [heapcheck_test_script]