#!/usr/bin/python
#
# Copyright (c) 2011 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.

"""Unit tests for main.py."""

import doctest
import optparse
import os
import re
import unittest

import chromite.lib.cros_build_lib as cros_lib
from chromite.lib import text_menu
from chromite.shell import main
from chromite.shell import utils
import mox


# Allow protected access, since we are closely partnered with the
# code that we're testing...
#
# pylint: disable=W0212

# Needed to make pylint not yell so much about mocked out stuff
# (it yells about AndReturn, MultipleTimes, ...).
#
# TODO(dianders): Any better solution than this heavy hammer?
#
# pylint: disable=E1101, E1103

# Just being a unittest.TestCase gives us 14 public methods.  Unless we
# disable this, we can only have 6 tests in a TestCase.  That's not enough.
#
# pylint: disable=R0904


class _DeathException(Exception):
  """A bogus exception used by the mock out of cros_lib.Die."""
  pass


class TestFindCommand(unittest.TestCase):
  """Test main._FindCommand."""
  # TODO(dianders): Add a test where I override main._COMMAND_HANDLERS
  # and main._COMMAND_STRS so that I can test more of _FindCommand().

  def setUp(self):
    """Test initialization."""
    # Create our mox and stub out function calls used by _FindCommand()...
    self.mox = mox.Mox()
    self.mox.StubOutWithMock(cros_lib, 'Die')
    self.mox.StubOutWithMock(text_menu, 'TextMenu')

  def tearDown(self):
    """Test cleanup."""
    # Unset stubs...
    self.mox.UnsetStubs()

  def testInvalidCommand(self):
    """Test that _FindCommand('implode') causes cros_lib.Die()."""
    # Should be a call to cros_lib.Die.  We'll have it fake a _DeathException...
    cros_lib.Die(mox.IsA(basestring)).AndRaise(_DeathException)

    # Run the command and verify proper mocks were called...
    self.mox.ReplayAll()
    self.assertRaises(_DeathException, main._FindCommand, 'implode')
    self.mox.VerifyAll()

  def testBlankCommandWithQuit(self):
    """Test that _FindCommand('') shows menu, mocking quit.

    This tests the case that the user quit out of the menu without choosing
    anything.
    """
    # Should be one call to TextMenu, which will return None for quit.
    text_menu.TextMenu(mox.IsA(list),
                       mox.IsA(basestring),
                       menu_width=0).AndReturn(None)

    # Should die in response to the quit.
    cros_lib.Die(mox.IsA(basestring)).AndRaise(_DeathException)

    # Run the command and verify proper mocks were called...
    self.mox.ReplayAll()
    self.assertRaises(_DeathException, main._FindCommand, '')
    self.mox.VerifyAll()

  def testBlankCommandWithChoice0(self):
    """Test that _FindCommand('') shows menu, mocking choice 0.

    This tests the case that the user chose choice 0 for the menu.
    """
    # Should be one call to TextMenu, which will return item 0.
    text_menu.TextMenu(mox.IsA(list),
                       mox.IsA(basestring),
                       menu_width=0).AndReturn(0)

    # Run the command and verify proper mocks were called...
    self.mox.ReplayAll()
    cmd_str = main._FindCommand('')
    self.mox.VerifyAll()

    self.assertTrue(isinstance(cmd_str, basestring),
                    '_FindCommand should return a string')
    self.assertTrue(bool(cmd_str),
                    '_FindCommand should not return a blank string')

  def _TestExactCommand(self, cmd_to_find):
    """Helper for tests that try to find an exact match.

    Args:
      cmd_to_find: The name of the command to find, like 'Build', ...
    """
    # Expect no mocks to be called...

    # Run the command and verify proper mocks were called...
    self.mox.ReplayAll()
    cmd_str = main._FindCommand(cmd_to_find)
    self.mox.VerifyAll()

    self.assertEqual(cmd_str, cmd_to_find.lower(),
                     '_FindCommand("%s") should return "%s" back.' %
                     (cmd_to_find, cmd_to_find.lower()))

  def testCaseSensitiveBuild(self):
    """Test that _FindCommand('build') returns 'build'.

    The command matching should be case sensitive.
    """
    self._TestExactCommand('build')

  def testCaseInsensitiveBuild(self):
    """Test that _FindCommand('BUiLD') returns 'build'.

    The command matching should be case insensitive.
    """
    self._TestExactCommand('BUiLD')

  def testShCommand(self):
    """Test that _FindCommand('sh') returns 'shell'.

    This serves two purposes:
    1. Test the 'prefix' feature of _FindCommand
    2. Validate that nobody has introduced another command that starts with
       'sh', since it's expected that many people will use this to invoke the
       shell.
    """
    # _FindCommand should give us a message that it has interpreted sh as shell.

    # Run the command and verify proper mocks were called...
    self.mox.ReplayAll()
    cmd_str = main._FindCommand('sh')
    self.mox.VerifyAll()

    self.assertEqual(cmd_str, 'shell',
                     '_FindCommand("sh") should return "shell" back.')


class TestFindSpec(unittest.TestCase):
  """Test utils.FindSpec."""

  def setUp(self):
    """Test initialization."""
    # Create our mox and stub out function calls used by _FindSpec()...
    self.mox = mox.Mox()
    self.mox.StubOutWithMock(os, 'listdir')
    self.mox.StubOutWithMock(os.path, 'isfile')
    self.mox.StubOutWithMock(cros_lib, 'Die')
    self.mox.StubOutWithMock(text_menu, 'TextMenu')

  def tearDown(self):
    """Test cleanup."""
    # Unset stubs...
    self.mox.UnsetStubs()

  def testInvalidSpec(self):
    """Test that _FindSpec('bogusSpec') causes cros_lib.Die()."""
    # Pass this spec name...
    spec_name = 'bogusSpec'

    # We'll tell mox to say that these specs exist...
    dir_list = ['x87-toadstool.spec', 'x87-luigi.SPeC', 'x88-princess.spec',
                '_default']

    # This spec doesn't represent any full path.
    os.path.isfile(spec_name).AndReturn(False)

    # This spec isn't found in our search path.
    os.path.isfile(mox.Regex('^/.*%s.spec$' % spec_name)).MultipleTimes(
        ).AndReturn(False)

    # Give the fake directory listing...
    os.listdir(mox.IsA(basestring)).MultipleTimes().AndReturn(dir_list)

    # Should be a call to cros_lib.Die.  We'll have it fake a _DeathException...
    cros_lib.Die(mox.IsA(basestring)).AndRaise(_DeathException)

    # Run the command and verify proper mocks were called...
    self.mox.ReplayAll()
    self.assertRaises(_DeathException, utils.FindSpec, 'bogusSpec')
    self.mox.VerifyAll()

  def testFullPath(self):
    """Test that _FindSpec(full_path) returns full_path.

    _FindSpec is defined so that if you pass a full file path to it, it
    should just return that.  It doesn't need to have any special suffix or
    live in a spec folder.
    """
    # Pass this spec name...
    spec_name = __file__

    # Just say that this is a full path...
    os.path.isfile(spec_name).AndReturn(True)

    # Run the command and verify proper mocks were called...
    self.mox.ReplayAll()
    path = utils.FindSpec(spec_name)
    self.mox.VerifyAll()

    self.assertEqual(path, spec_name,
                     '_FindSpec() should just return param if full path.')

  def testExactSpecName(self):
    """Test that _FindSpec(exact_spec_name) returns the path for the spec."""
    # We'll search for this bogus spec; we'll use mox to pretend it exists in
    # the search path.
    spec_name = 'y87-luigi'

    # This spec doesn't represent any full path
    os.path.isfile(spec_name).AndReturn(False)

    # When we look through the search path for this spec (with .spec at
    # the end), we will consider the spec to be found.
    os.path.isfile(mox.Regex('^/.*%s.spec$' % spec_name)).AndReturn(True)

    # Run the command and verify proper mocks were called...
    self.mox.ReplayAll()
    spec_path = utils.FindSpec(spec_name)
    self.mox.VerifyAll()

    self.assertTrue(re.search('^/.*%s.spec$' % spec_name, spec_path),
                    '_FindSpec() should have returned absolute path for spec.')

  def testUniqueSpecName(self):
    """Test that _FindSpec(unique_part_name) returns the path for the spec."""
    # We'll search for this spec.  Weird capitalization on purpose to test
    # case sensitiveness.
    spec_name = 'ToaDSTooL'

    # We'll tell mox to say that these specs exist in the first directory...
    dir_list = ['_default',
                'x87-luigi.spec', 'x87-toadstool.SPeC', 'x88-princess.spec']

    # We expect it to find this spec.
    expected_result = 'x87-toadstool.SPeC'

    # Self-checks for test code...
    assert dir_list == sorted(dir_list)

    # This spec doesn't represent any full path.
    os.path.isfile(spec_name).AndReturn(False)

    # This spec isn't found in our search path.
    os.path.isfile(mox.Regex('^/.*%s.spec$' % spec_name)).MultipleTimes(
        ).AndReturn(False)

    # Return our directory listing.
    # TODO(dianders): How to make first mocked call return dir_list and
    # subsequent return []
    os.listdir(mox.IsA(basestring)).AndReturn(dir_list)

    os.path.isfile(mox.Regex('^/.*%s$' % expected_result)).AndReturn(True)

    # Run the command and verify proper mocks were called...
    self.mox.ReplayAll()
    spec_path = utils.FindSpec(spec_name)
    self.mox.VerifyAll()

    self.assertTrue(re.search('^/.*%s$' % expected_result, spec_path),
                    '_FindSpec("%s") incorrectly returned "%s".' %
                    (spec_name, spec_path))

  def _TestBlankSpecName(self, menu_return):
    """Helper for tests passing a blank spec name.

    Args:
      menu_return: This value is returned by TextMenu.  Could be none or an
          integer index into the dir_list of this function.
    """
    # We'll search for this spec.
    spec_name = ''

    # We'll tell mox to say that these specs exist in the first directory...
    # ...only valid specs to make it easier to compare things.
    dir_list = ['x87-luigi.spec', 'x87-toadstool.SPeC', 'x88-princess.spec']
    num_specs = len(dir_list)

    # Self-checks for test code...
    assert menu_return < len(dir_list)
    assert dir_list == sorted(dir_list)

    # This spec doesn't represent any full path.
    os.path.isfile(spec_name).AndReturn(False)

    # Return our directory listing.
    # TODO(dianders): How to make first mocked call return dir_list and
    # subsequent return []
    os.listdir(mox.IsA(basestring)).AndReturn(dir_list)

    for i in xrange(num_specs):
      os.path.isfile(mox.Regex('^/.*%s$' % dir_list[i])).AndReturn(True)

    # We expect there to be 1 more item than we passed in, since we account
    # for 'HOST'.
    check_num_items_fn = lambda items: len(items) == (num_specs + 1)

    # Add 1 to menu_return, since 'HOST' is first...
    if menu_return is None:
      adjusted_menu_return = menu_return
    else:
      adjusted_menu_return = menu_return + 1

    # Should be one call to TextMenu, which will return menu_return.
    text_menu.TextMenu(mox.And(mox.IsA(list), mox.Func(check_num_items_fn)),
                       mox.IsA(basestring)).AndReturn(adjusted_menu_return)

    # Should die in response to the quit if directed to quit.
    if menu_return is None:
      cros_lib.Die(mox.IsA(basestring)).AndRaise(_DeathException)

    # Run the command and verify proper mocks were called...
    self.mox.ReplayAll()
    if menu_return is None:
      self.assertRaises(_DeathException, utils.FindSpec, spec_name)
    else:
      spec_path = utils.FindSpec(spec_name)
    self.mox.VerifyAll()

    if menu_return is not None:
      expected_result = dir_list[menu_return]
      self.assertTrue(re.search('^/.*%s$' % expected_result, spec_path),
                      '_FindSpec("%s") incorrectly returned "%s".' %
                      (spec_name, spec_path))

  def testBlankSpecNameWithQuit(self):
    """Test that _FindSpec('') shows menu, mocking quit."""
    self._TestBlankSpecName(None)

  def testBlankSpecNameWithChoice0(self):
    """Test that _FindSpec('') shows menu, mocking choice 0."""
    self._TestBlankSpecName(0)

  def testPartialSpecNameWithChoice0(self):
    """Test that _FindSpec(non_unique_str) shows menu, mocking choice 0."""
    # We'll search for this spec.
    spec_name = 'x87'

    # We'll tell mox to say that these specs exist in the first directory...
    dir_list = ['_default',
                'x87-luigi.spec', 'x87-toadstool.SPeC', 'x88-princess.spec']

    # We expect 2 matches and should get back luigi as choice 0.
    matches = ['x87-luigi.spec', 'x87-toadstool.SPeC']
    num_match = len(matches)
    expected_result = 'x87-luigi.spec'

    # Self-checks for test code...
    assert dir_list == sorted(dir_list)

    # This spec doesn't represent any full path.
    os.path.isfile(spec_name).AndReturn(False)

    # This spec isn't found in our search path.
    os.path.isfile(mox.Regex('^/.*%s.spec$' % spec_name)).MultipleTimes(
        ).AndReturn(False)

    # Return our directory listing.
    # TODO(dianders): How to make first mocked call return dir_list and
    # subsequent return []
    os.listdir(mox.IsA(basestring)).AndReturn(dir_list)

    for i in xrange(num_match):
      os.path.isfile(mox.Regex('^/.*%s$' % matches[i])).AndReturn(True)

    # Should be one call to TextMenu, which will return 0.
    text_menu.TextMenu(mox.And(mox.IsA(list),
                               mox.Func(lambda items: len(items) == num_match)),
                       mox.IsA(basestring)).AndReturn(0)

    # Run the command and verify proper mocks were called...
    self.mox.ReplayAll()
    spec_path = utils.FindSpec(spec_name)
    self.mox.VerifyAll()

    self.assertTrue(re.search('^/.*%s$' % expected_result, spec_path),
                    '_FindSpec("%s") incorrectly returned "%s".' %
                    (spec_name, spec_path))

class TestParseArguments(unittest.TestCase):
  """Test utils.FindSpec."""

  def setUp(self):
    """Test initialization."""
    self.parser = optparse.OptionParser()

    # Verbose defaults to full for now, just to keep people acclimatized to
    # vast amounts of comforting output.
    self.parser.add_option('-v', dest='verbose', default=3, type='int',
        help='Control verbosity: 0=silent, 1=progress, 3=full')
    self.parser.add_option('-q', action='store_const', dest='verbose', const=0,
        help='Be quieter (sets verbosity to 1)')

  def testEmpty(self):
    options, cmd, sub = main._ParseArguments(self.parser,
        [])
    self.assertEqual(options.verbose, 3)
    self.assertEqual(cmd, '')
    self.assertEqual(sub, [])

  def testBadOption(self):
    self.assertRaises(SystemExit, main._ParseArguments, self.parser,
        ['chromite', '--bad'])
    self.assertRaises(SystemExit, main._ParseArguments, self.parser,
        ['chromite', '--bad', 'build'])

  def testSubcmd(self):
    options, cmd, sub = main._ParseArguments(self.parser,
        ['chromite', 'build'])
    self.assertEqual(options.verbose, 3)
    self.assertEqual(cmd, 'build')
    self.assertEqual(sub, [])

  def testSubcmdQuiet(self):
    options, cmd, sub = main._ParseArguments(self.parser,
        ['chromite', '-q', 'build'])
    self.assertEqual(options.verbose, 0)
    self.assertEqual(cmd, 'build')
    self.assertEqual(sub, [])

  def testSubcmdVerbose2(self):
    options, cmd, sub = main._ParseArguments(self.parser,
        ['chromite', '-v2', 'build'])
    self.assertEqual(options.verbose, 2)
    self.assertEqual(cmd, 'build')
    self.assertEqual(sub, [])

  def testSubcmdVerbose4(self):
    options, cmd, sub = main._ParseArguments(self.parser,
        ['chromite', '-v', '4', 'build'])
    self.assertEqual(options.verbose, 4)
    self.assertEqual(cmd, 'build')
    self.assertEqual(sub, [])

  def testSubcmdArgs(self):
    options, cmd, sub = main._ParseArguments(self.parser,
        ['chromite', '-v', '4', 'build', 'seaboard', '--clean'])
    self.assertEqual(options.verbose, 4)
    self.assertEqual(cmd, 'build')
    self.assertEqual(sub, ['seaboard', '--clean'])

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