#!/usr/bin/env python
# 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.

import difflib
import os
import re
import unittest

import PRESUBMIT

class MockLogging(object):
  def __init__(self):
    self.lines = []

  def info(self, message):
    self.lines.append(message)

  def debug(self, message):
    self.lines.append(message)

class MockInputApi(object):
  def __init__(self):
    self.re = re
    self.os_path = os.path
    self.files = []
    self.is_committing = False
    self.logging = MockLogging()

  def AffectedFiles(self, include_deletes=None):
    return self.files


class MockOutputApi(object):
  class PresubmitResult(object):
    def __init__(self, message, items=None, long_text=''):
      self.message = message
      self.items = items
      self.long_text = long_text

  class PresubmitError(PresubmitResult):
    def __init__(self, message, items, long_text=''):
      MockOutputApi.PresubmitResult.__init__(self, message, items, long_text)
      self.type = 'error'

  class PresubmitPromptWarning(PresubmitResult):
    def __init__(self, message, items, long_text=''):
      MockOutputApi.PresubmitResult.__init__(self, message, items, long_text)
      self.type = 'warning'

  class PresubmitNotifyResult(PresubmitResult):
    def __init__(self, message, items, long_text=''):
      MockOutputApi.PresubmitResult.__init__(self, message, items, long_text)
      self.type = 'notify'


class MockFile(object):
  def __init__(self, local_path, old_contents, new_contents):
    self._local_path = local_path
    self._new_contents = new_contents
    self._old_contents = old_contents
    self._cached_changed_contents = None

  def ChangedContents(self):
    return self._changed_contents

  def NewContents(self):
    return self._new_contents

  def LocalPath(self):
    return self._local_path

  def IsDirectory(self):
    return False

  def GenerateScmDiff(self):
    result = ""
    for line in difflib.unified_diff(self._old_contents, self._new_contents,
                                     self._local_path, self._local_path):
      result += line
    return result

  # NOTE: This method is a copy of ChangeContents method of AffectedFile in
  # presubmit_support.py
  def ChangedContents(self):
    """Returns a list of tuples (line number, line text) of all new lines.

     This relies on the scm diff output describing each changed code section
     with a line of the form

     ^@@ <old line num>,<old size> <new line num>,<new size> @@$
    """
    if self._cached_changed_contents is not None:
      return self._cached_changed_contents[:]
    self._cached_changed_contents = []
    line_num = 0

    if self.IsDirectory():
      return []

    for line in self.GenerateScmDiff().splitlines():
      m = re.match(r'^@@ [0-9\,\+\-]+ \+([0-9]+)\,[0-9]+ @@', line)
      if m:
        line_num = int(m.groups(1)[0])
        continue
      if line.startswith('+') and not line.startswith('++'):
        self._cached_changed_contents.append((line_num, line[1:]))
      if not line.startswith('-'):
        line_num += 1
    return self._cached_changed_contents[:]


class MockChange(object):
  def __init__(self, changed_files):
    self._changed_files = changed_files

  def LocalPaths(self):
    return self._changed_files


class HistogramValueCheckerTest(unittest.TestCase):
  TEST_FILE_PATTERN = "PRESUBMIT_test_new_file_%s.txt"

  def _ReadTextFileContents(self, path):
    """Given a path, returns a list of strings corresponding to the text lines
    in the file. Reads files in text format.

    """
    fo = open(path, 'r')
    try:
      contents = fo.readlines()
    finally:
      fo.close()
    return contents

  def _ReadInputFile(self):
    return self._ReadTextFileContents("PRESUBMIT_test_old_file.txt")

  def _PrepareTest(self, new_file_path):
    old_contents = self._ReadInputFile()
    if not new_file_path:
      new_contents = []
    else:
      new_contents = self._ReadTextFileContents(new_file_path)
    input_api = MockInputApi()
    mock_file = MockFile(PRESUBMIT.HistogramValueChecker.LOCAL_PATH,
                         old_contents,
                         new_contents)
    input_api.files.append(mock_file)
    output_api = MockOutputApi()
    return input_api, output_api

  def _RunTest(self, new_file_path):
    input_api, output_api = self._PrepareTest(new_file_path)
    checker = PRESUBMIT.HistogramValueChecker(input_api, output_api)
    results = checker.Run()
    return results

  def testDeleteFile(self):
    results = self._RunTest(new_file_path=None)
    # TODO(rpaquay) How to check it's the expected warning?'
    self.assertEquals(1, len(results),
                      "We hould get a single warning about file deletion.")

  def testSimpleValidEdit(self):
    results = self._RunTest(self.TEST_FILE_PATTERN % "1")
    # TODO(rpaquay) How to check it's the expected warning?'
    self.assertEquals(0, len(results),
                      "We should get no warning for simple edits.")

  def testSingleDeletionOfEntry(self):
    results = self._RunTest(self.TEST_FILE_PATTERN % "2")
    # TODO(rpaquay) How to check it's the expected warning?'
    self.assertEquals(1, len(results),
                      "We should get a warning for an entry deletion.")

  def testSingleRenameOfEntry(self):
    results = self._RunTest(self.TEST_FILE_PATTERN % "3")
    # TODO(rpaquay) How to check it's the expected warning?'
    self.assertEquals(1, len(results),
                      "We should get a warning for an entry rename, even "
                      "though it is not optimal.")

  def testMissingEnumStartOfEntry(self):
    results = self._RunTest(self.TEST_FILE_PATTERN % "4")
    # TODO(rpaquay) How to check it's the expected warning?'
    self.assertEquals(1, len(results),
                      "We should get a warning for a missing enum marker.")

  def testMissingEnumEndOfEntry(self):
    results = self._RunTest(self.TEST_FILE_PATTERN % "5")
    # TODO(rpaquay) How to check it's the expected warning?'
    self.assertEquals(1, len(results),
                      "We should get a warning for a missing enum marker.")

  def testInvertedEnumMarkersOfEntry(self):
    results = self._RunTest(self.TEST_FILE_PATTERN % "6")
    # TODO(rpaquay) How to check it's the expected warning?'
    self.assertEquals(1, len(results),
                      "We should get a warning for inverted enum markers.")

  def testMultipleInvalidEdits(self):
    results = self._RunTest(self.TEST_FILE_PATTERN % "7")
    # TODO(rpaquay) How to check it's the expected warning?'
    self.assertEquals(3, len(results),
                      "We should get 3 warnings (one per edit).")

  def testSingleInvalidInserts(self):
    results = self._RunTest(self.TEST_FILE_PATTERN % "8")
    # TODO(rpaquay) How to check it's the expected warning?'
    self.assertEquals(1, len(results),
                      "We should get a warning for a single invalid "
                      "insertion inside the enum.")

  def testMulitpleValidInserts(self):
    results = self._RunTest(self.TEST_FILE_PATTERN % "9")
    # TODO(rpaquay) How to check it's the expected warning?'
    self.assertEquals(0, len(results),
                      "We should not get a warning mulitple valid edits")

  def testSingleValidDeleteOutsideOfEnum(self):
    results = self._RunTest(self.TEST_FILE_PATTERN % "10")
    # TODO(rpaquay) How to check it's the expected warning?'
    self.assertEquals(0, len(results),
                      "We should not get a warning for a deletion outside of "
                      "the enum")


if __name__ == '__main__':
  unittest.main()
