# Copyright 2015 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.

"""Tests the `cros shell` command."""

from __future__ import print_function

from chromite.cros.commands import cros_shell
from chromite.cros.commands import init_unittest
from chromite.lib import cros_build_lib
from chromite.lib import cros_test_lib
from chromite.lib import remote_access


class MockShellCommand(init_unittest.MockCommand):
  """Mock out the `cros shell` command."""
  TARGET = 'chromite.cros.commands.cros_shell.ShellCommand'
  TARGET_CLASS = cros_shell.ShellCommand
  COMMAND = 'shell'

  def __init__(self, *args, **kwargs):
    init_unittest.MockCommand.__init__(self, *args, **kwargs)

  def Run(self, inst):
    return init_unittest.MockCommand.Run(self, inst)


def _SshConnectError():
  """Returns an error indicating a general SSH error."""
  return remote_access.SSHConnectionError('(test) SSH Error')


def _KeyMismatchError():
  """Returns an error indicating an SSH host key mismatch."""
  return remote_access.SSHConnectionError(
      '(test) REMOTE HOST IDENTIFICATION HAS CHANGED')


class ShellTest(cros_test_lib.MockTempDirTestCase):
  """Test the flow of ShellCommand.run with the SSH methods mocked out."""

  DEVICE = '1.1.1.1'

  def SetupCommandMock(self, cmd_args):
    """Sets up the `cros shell` command mock."""
    self.cmd_mock = MockShellCommand(
        cmd_args, base_args=['--cache-dir', self.tempdir])
    self.StartPatcher(self.cmd_mock)

  def setUp(self):
    """Patches objects."""
    self.cmd_mock = None
    # Patch any functions we want to control that may get called by a test.
    self.remove_known_host_function = self.PatchObject(remote_access,
                                                       'RemoveKnownHost')
    self.prompt_function = self.PatchObject(cros_build_lib, 'BooleanPrompt')
    # Patch the remote_access.RemoteAccess object, then drill down to the
    # RemoteSh() function which would do the actual SSH call in order to
    # easily set and check test conditions.
    self.patched_remote_access = self.PatchObject(remote_access, 'RemoteAccess')
    self.remote_access_instance = self.patched_remote_access.return_value
    self.remote_sh_function = self.remote_access_instance.RemoteSh

  def testSshInteractive(self):
    """Tests flow for an interactive session.

    User should not be prompted for input, and SSH should be attempted
    once.
    """
    self.SetupCommandMock([self.DEVICE])
    self.cmd_mock.inst.Run()
    self.assertEqual(self.remote_sh_function.call_count, 1)
    self.assertFalse(self.prompt_function.called)
    # Make sure that RemoteSh() started an interactive session (no cmd).
    self.assertEqual(self.remote_sh_function.call_args[0][0], [])

  def testSshNonInteractiveSingleArg(self):
    """Tests a non-interactive command as a single argument.

    Example: cros shell 1.1.1.1 "ls -l /etc"
    """
    self.SetupCommandMock([self.DEVICE, 'ls -l /etc'])
    self.cmd_mock.inst.Run()
    self.assertEqual(self.remote_sh_function.call_args[0][0], ['ls -l /etc'])

  def testSshNonInteractiveMultipleArgs(self):
    """Tests a non-interactive command as multiple arguments with "--".

    Example: cros shell 1.1.1.1 -- ls -l /etc
    """
    self.SetupCommandMock([self.DEVICE, '--', 'ls', '-l', '/etc'])
    self.cmd_mock.inst.Run()
    self.assertEqual(self.remote_sh_function.call_args[0][0],
                     ['ls', '-l', '/etc'])

  def testSshReturnValue(self):
    """Tests that `cros shell` returns the exit code of RemoteSh()."""
    self.SetupCommandMock([self.DEVICE])
    self.remote_sh_function.return_value = cros_build_lib.CommandResult(
        returncode=42)
    self.assertEqual(self.cmd_mock.inst.Run(), 42)

  def testSshKeyChangeOK(self):
    """Tests a host SSH key changing but the user giving it the OK.

    User should be prompted, SSH should be attempted twice, and host
    keys should be removed.
    """
    self.SetupCommandMock([self.DEVICE])
    # RemoteSh() gives a key mismatch error the first time only.
    self.remote_sh_function.side_effect = [_KeyMismatchError(), None]
    # User chooses to continue.
    self.prompt_function.return_value = True
    with cros_test_lib.OutputCapturer():
      self.cmd_mock.inst.Run()
    self.assertTrue(self.prompt_function.called)
    self.assertEqual(self.remote_sh_function.call_count, 2)
    self.assertTrue(self.remove_known_host_function.called)

  def testSshKeyChangeAbort(self):
    """Tests a host SSH key changing and the user canceling.

    User should be prompted, but SSH should only be attempted once, and
    no host keys should be removed.
    """
    self.SetupCommandMock([self.DEVICE])
    self.remote_sh_function.side_effect = _KeyMismatchError()
    # User chooses to abort.
    self.prompt_function.return_value = False
    with cros_test_lib.OutputCapturer():
      self.cmd_mock.inst.Run()
    self.assertTrue(self.prompt_function.called)
    self.assertEqual(self.remote_sh_function.call_count, 1)
    self.assertFalse(self.remove_known_host_function.called)

  def testSshConnectError(self):
    """Tests an SSH error other than a host key mismatch.

    User should not be prompted, SSH should only be attempted once, and
    no host keys should be removed.
    """
    self.SetupCommandMock([self.DEVICE])
    self.remote_sh_function.side_effect = _SshConnectError()
    with cros_test_lib.OutputCapturer():
      self.cmd_mock.inst.Run()
    self.assertFalse(self.prompt_function.called)
    self.assertEqual(self.remote_sh_function.call_count, 1)
    self.assertFalse(self.remove_known_host_function.called)
