#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright 2020 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 git helper functions."""

from __future__ import print_function

import os
import subprocess
import tempfile
import unittest
import unittest.mock as mock

import git

# These are unittests; protected access is OK to a point.
# pylint: disable=protected-access


class HelperFunctionsTest(unittest.TestCase):
  """Test class for updating LLVM hashes of packages."""

  @mock.patch.object(os.path, 'isdir', return_value=False)
  def testFailedToCreateBranchForInvalidDirectoryPath(self, mock_isdir):
    path_to_repo = '/invalid/path/to/repo'
    branch = 'branch-name'

    # Verify the exception is raised when provided an invalid directory path.
    with self.assertRaises(ValueError) as err:
      git.CreateBranch(path_to_repo, branch)

    self.assertEqual(
        str(err.exception),
        'Invalid directory path provided: %s' % path_to_repo)

    mock_isdir.assert_called_once()

  @mock.patch.object(os.path, 'isdir', return_value=True)
  @mock.patch.object(subprocess, 'check_output', return_value=None)
  def testSuccessfullyCreatedBranch(self, mock_command_output, mock_isdir):
    path_to_repo = '/path/to/repo'
    branch = 'branch-name'

    git.CreateBranch(path_to_repo, branch)

    mock_isdir.assert_called_once_with(path_to_repo)

    self.assertEqual(mock_command_output.call_count, 2)

  @mock.patch.object(os.path, 'isdir', return_value=False)
  def testFailedToDeleteBranchForInvalidDirectoryPath(self, mock_isdir):
    path_to_repo = '/invalid/path/to/repo'
    branch = 'branch-name'

    # Verify the exception is raised on an invalid repo path.
    with self.assertRaises(ValueError) as err:
      git.DeleteBranch(path_to_repo, branch)

    self.assertEqual(
        str(err.exception),
        'Invalid directory path provided: %s' % path_to_repo)

    mock_isdir.assert_called_once()

  @mock.patch.object(os.path, 'isdir', return_value=True)
  @mock.patch.object(subprocess, 'check_output', return_value=None)
  def testSuccessfullyDeletedBranch(self, mock_command_output, mock_isdir):
    path_to_repo = '/valid/path/to/repo'
    branch = 'branch-name'

    git.DeleteBranch(path_to_repo, branch)

    mock_isdir.assert_called_once_with(path_to_repo)

    self.assertEqual(mock_command_output.call_count, 3)

  @mock.patch.object(os.path, 'isdir', return_value=False)
  def testFailedToUploadChangesForInvalidDirectoryPath(self, mock_isdir):
    path_to_repo = '/some/path/to/repo'
    branch = 'update-LLVM_NEXT_HASH-a123testhash3'
    commit_messages = ['Test message']

    # Verify exception is raised when on an invalid repo path.
    with self.assertRaises(ValueError) as err:
      git.UploadChanges(path_to_repo, branch, commit_messages)

    self.assertEqual(
        str(err.exception), 'Invalid path provided: %s' % path_to_repo)

    mock_isdir.assert_called_once()

  @mock.patch.object(os.path, 'isdir', return_value=True)
  @mock.patch.object(subprocess, 'check_output')
  @mock.patch.object(tempfile, 'NamedTemporaryFile')
  def testSuccessfullyUploadedChangesForReview(self, mock_tempfile,
                                               mock_commands, mock_isdir):

    path_to_repo = '/some/path/to/repo'
    branch = 'branch-name'
    commit_messages = ['Test message']
    mock_tempfile.return_value.__enter__.return_value.name = 'tmp'

    # A test CL generated by `repo upload`.
    mock_commands.side_effect = [
        None,
        ('remote: https://chromium-review.googlesource.'
         'com/c/chromiumos/overlays/chromiumos-overlay/'
         '+/193147 Fix stdout')
    ]
    change_list = git.UploadChanges(path_to_repo, branch, commit_messages)

    self.assertEqual(change_list.cl_number, 193147)

    mock_isdir.assert_called_once_with(path_to_repo)

    expected_command = [
        'git', 'commit', '-F',
        mock_tempfile.return_value.__enter__.return_value.name
    ]
    self.assertEqual(mock_commands.call_args_list[0],
                     mock.call(expected_command, cwd=path_to_repo))

    expected_cmd = [
        'repo', 'upload', '--yes', '--ne', '--no-verify',
        '--br=%s' % branch
    ]
    self.assertEqual(
        mock_commands.call_args_list[1],
        mock.call(
            expected_cmd,
            stderr=subprocess.STDOUT,
            cwd=path_to_repo,
            encoding='utf-8'))

    self.assertEqual(
        change_list.url,
        'https://chromium-review.googlesource.com/c/chromiumos/overlays/'
        'chromiumos-overlay/+/193147')


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