#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright 2020 The ChromiumOS 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 for rust_uprev.py"""

import os
import shutil
import subprocess
import tempfile
import unittest
from pathlib import Path
from unittest import mock

from llvm_tools import git

import rust_uprev
from rust_uprev import RustVersion


def _fail_command(cmd, *_args, **_kwargs):
  err = subprocess.CalledProcessError(returncode=1, cmd=cmd)
  err.stderr = b'mock failure'
  raise err


class FetchDistfileTest(unittest.TestCase):
  """Tests rust_uprev.fetch_distfile_from_mirror()"""

  @mock.patch.object(rust_uprev, 'get_distdir', return_value='/fake/distfiles')
  @mock.patch.object(subprocess, 'call', side_effect=_fail_command)
  def test_fetch_difstfile_fail(self, *_args) -> None:
    with self.assertRaises(subprocess.CalledProcessError):
      rust_uprev.fetch_distfile_from_mirror('test_distfile.tar.gz')

  @mock.patch.object(rust_uprev,
                     'get_command_output_unchecked',
                     return_value='AccessDeniedException: Access denied.')
  @mock.patch.object(rust_uprev, 'get_distdir', return_value='/fake/distfiles')
  @mock.patch.object(subprocess, 'call', return_value=0)
  def test_fetch_distfile_acl_access_denied(self, *_args) -> None:
    rust_uprev.fetch_distfile_from_mirror('test_distfile.tar.gz')

  @mock.patch.object(
      rust_uprev,
      'get_command_output_unchecked',
      return_value='[ { "entity": "allUsers", "role": "READER" } ]')
  @mock.patch.object(rust_uprev, 'get_distdir', return_value='/fake/distfiles')
  @mock.patch.object(subprocess, 'call', return_value=0)
  def test_fetch_distfile_acl_ok(self, *_args) -> None:
    rust_uprev.fetch_distfile_from_mirror('test_distfile.tar.gz')

  @mock.patch.object(
      rust_uprev,
      'get_command_output_unchecked',
      return_value='[ { "entity": "___fake@google.com", "role": "OWNER" } ]')
  @mock.patch.object(rust_uprev, 'get_distdir', return_value='/fake/distfiles')
  @mock.patch.object(subprocess, 'call', return_value=0)
  def test_fetch_distfile_acl_wrong(self, *_args) -> None:
    with self.assertRaisesRegex(Exception, 'allUsers.*READER'):
      with self.assertLogs(level='ERROR') as log:
        rust_uprev.fetch_distfile_from_mirror('test_distfile.tar.gz')
        self.assertIn(
            '[ { "entity": "___fake@google.com", "role": "OWNER" } ]',
            '\n'.join(log.output))


class FindEbuildPathTest(unittest.TestCase):
  """Tests for rust_uprev.find_ebuild_path()"""

  def test_exact_version(self):
    with tempfile.TemporaryDirectory() as tmpdir:
      ebuild = Path(tmpdir, 'test-1.3.4.ebuild')
      ebuild.touch()
      Path(tmpdir, 'test-1.2.3.ebuild').touch()
      result = rust_uprev.find_ebuild_path(tmpdir, 'test',
                                           rust_uprev.RustVersion(1, 3, 4))
      self.assertEqual(result, ebuild)

  def test_no_version(self):
    with tempfile.TemporaryDirectory() as tmpdir:
      ebuild = Path(tmpdir, 'test-1.2.3.ebuild')
      ebuild.touch()
      result = rust_uprev.find_ebuild_path(tmpdir, 'test')
      self.assertEqual(result, ebuild)

  def test_patch_version(self):
    with tempfile.TemporaryDirectory() as tmpdir:
      ebuild = Path(tmpdir, 'test-1.3.4-r3.ebuild')
      ebuild.touch()
      Path(tmpdir, 'test-1.2.3.ebuild').touch()
      result = rust_uprev.find_ebuild_path(tmpdir, 'test',
                                           rust_uprev.RustVersion(1, 3, 4))
      self.assertEqual(result, ebuild)


class RustVersionTest(unittest.TestCase):
  """Tests for RustVersion class"""

  def test_str(self):
    obj = rust_uprev.RustVersion(major=1, minor=2, patch=3)
    self.assertEqual(str(obj), '1.2.3')

  def test_parse_version_only(self):
    expected = rust_uprev.RustVersion(major=1, minor=2, patch=3)
    actual = rust_uprev.RustVersion.parse('1.2.3')
    self.assertEqual(expected, actual)

  def test_parse_ebuild_name(self):
    expected = rust_uprev.RustVersion(major=1, minor=2, patch=3)
    actual = rust_uprev.RustVersion.parse_from_ebuild('rust-1.2.3.ebuild')
    self.assertEqual(expected, actual)

    actual = rust_uprev.RustVersion.parse_from_ebuild('rust-1.2.3-r1.ebuild')
    self.assertEqual(expected, actual)

  def test_parse_fail(self):
    with self.assertRaises(AssertionError) as context:
      rust_uprev.RustVersion.parse('invalid-rust-1.2.3')
    self.assertEqual("failed to parse 'invalid-rust-1.2.3'",
                     str(context.exception))


class PrepareUprevTest(unittest.TestCase):
  """Tests for prepare_uprev step in rust_uprev"""

  def setUp(self):
    self.bootstrap_version = rust_uprev.RustVersion(1, 1, 0)
    self.version_old = rust_uprev.RustVersion(1, 2, 3)
    self.version_new = rust_uprev.RustVersion(1, 3, 5)

  @mock.patch.object(rust_uprev,
                     'find_ebuild_for_rust_version',
                     return_value='/path/to/ebuild')
  @mock.patch.object(rust_uprev, 'find_ebuild_path')
  @mock.patch.object(rust_uprev, 'get_command_output')
  def test_success_with_template(self, mock_command, mock_find_ebuild,
                                 _ebuild_for_version):
    bootstrap_ebuild_path = Path(
        '/path/to/rust-bootstrap/',
        f'rust-bootstrap-{self.bootstrap_version}.ebuild')
    mock_find_ebuild.return_value = bootstrap_ebuild_path
    expected = (self.version_old, '/path/to/ebuild', self.bootstrap_version)
    actual = rust_uprev.prepare_uprev(rust_version=self.version_new,
                                      template=self.version_old)
    self.assertEqual(expected, actual)
    mock_command.assert_not_called()

  @mock.patch.object(rust_uprev,
                     'find_ebuild_for_rust_version',
                     return_value='/path/to/ebuild')
  @mock.patch.object(rust_uprev,
                     'get_rust_bootstrap_version',
                     return_value=RustVersion(0, 41, 12))
  @mock.patch.object(rust_uprev, 'get_command_output')
  def test_return_none_with_template_larger_than_input(self, mock_command,
                                                       *_args):
    ret = rust_uprev.prepare_uprev(rust_version=self.version_old,
                                   template=self.version_new)
    self.assertIsNone(ret)
    mock_command.assert_not_called()

  @mock.patch.object(rust_uprev, 'find_ebuild_path')
  @mock.patch.object(os.path, 'exists')
  @mock.patch.object(rust_uprev, 'get_command_output')
  def test_success_without_template(self, mock_command, mock_exists,
                                    mock_find_ebuild):
    rust_ebuild_path = f'/path/to/rust/rust-{self.version_old}-r3.ebuild'
    mock_command.return_value = rust_ebuild_path
    bootstrap_ebuild_path = Path(
        '/path/to/rust-bootstrap',
        f'rust-bootstrap-{self.bootstrap_version}.ebuild')
    mock_find_ebuild.return_value = bootstrap_ebuild_path
    expected = (self.version_old, rust_ebuild_path, self.bootstrap_version)
    actual = rust_uprev.prepare_uprev(rust_version=self.version_new,
                                      template=None)
    self.assertEqual(expected, actual)
    mock_command.assert_called_once_with(['equery', 'w', 'rust'])
    mock_exists.assert_not_called()

  @mock.patch.object(rust_uprev,
                     'get_rust_bootstrap_version',
                     return_value=RustVersion(0, 41, 12))
  @mock.patch.object(os.path, 'exists')
  @mock.patch.object(rust_uprev, 'get_command_output')
  def test_return_none_with_ebuild_larger_than_input(self, mock_command,
                                                     mock_exists, *_args):
    mock_command.return_value = f'/path/to/rust/rust-{self.version_new}.ebuild'
    ret = rust_uprev.prepare_uprev(rust_version=self.version_old,
                                   template=None)
    self.assertIsNone(ret)
    mock_exists.assert_not_called()

  def test_prepare_uprev_from_json(self):
    ebuild_path = '/path/to/the/ebuild'
    json_result = (list(self.version_new), ebuild_path,
                   list(self.bootstrap_version))
    expected = (self.version_new, ebuild_path, self.bootstrap_version)
    actual = rust_uprev.prepare_uprev_from_json(json_result)
    self.assertEqual(expected, actual)


class UpdateEbuildTest(unittest.TestCase):
  """Tests for update_ebuild step in rust_uprev"""
  ebuild_file_before = """
BOOTSTRAP_VERSION="1.2.0"
    """
  ebuild_file_after = """
BOOTSTRAP_VERSION="1.3.6"
    """

  def test_success(self):
    mock_open = mock.mock_open(read_data=self.ebuild_file_before)
    # ebuild_file and new bootstrap version are deliberately different
    ebuild_file = '/path/to/rust/rust-1.3.5.ebuild'
    with mock.patch('builtins.open', mock_open):
      rust_uprev.update_ebuild(ebuild_file,
                               rust_uprev.RustVersion.parse('1.3.6'))
    mock_open.return_value.__enter__().write.assert_called_once_with(
        self.ebuild_file_after)

  def test_fail_when_ebuild_misses_a_variable(self):
    mock_open = mock.mock_open(read_data='')
    ebuild_file = '/path/to/rust/rust-1.3.5.ebuild'
    with mock.patch('builtins.open', mock_open):
      with self.assertRaises(RuntimeError) as context:
        rust_uprev.update_ebuild(ebuild_file,
                                 rust_uprev.RustVersion.parse('1.2.0'))
    self.assertEqual('BOOTSTRAP_VERSION not found in rust ebuild',
                     str(context.exception))


class UpdateManifestTest(unittest.TestCase):
  """Tests for update_manifest step in rust_uprev"""

  # pylint: disable=protected-access
  def _run_test_flip_mirror(self, before, after, add, expect_write):
    mock_open = mock.mock_open(read_data=f'RESTRICT="{before}"')
    with mock.patch('builtins.open', mock_open):
      rust_uprev.flip_mirror_in_ebuild('', add=add)
    if expect_write:
      mock_open.return_value.__enter__().write.assert_called_once_with(
          f'RESTRICT="{after}"')

  def test_add_mirror_in_ebuild(self):
    self._run_test_flip_mirror(before='variable1 variable2',
                               after='variable1 variable2 mirror',
                               add=True,
                               expect_write=True)

  def test_remove_mirror_in_ebuild(self):
    self._run_test_flip_mirror(before='variable1 variable2 mirror',
                               after='variable1 variable2',
                               add=False,
                               expect_write=True)

  def test_add_mirror_when_exists(self):
    self._run_test_flip_mirror(before='variable1 variable2 mirror',
                               after='variable1 variable2 mirror',
                               add=True,
                               expect_write=False)

  def test_remove_mirror_when_not_exists(self):
    self._run_test_flip_mirror(before='variable1 variable2',
                               after='variable1 variable2',
                               add=False,
                               expect_write=False)

  @mock.patch.object(rust_uprev, 'flip_mirror_in_ebuild')
  @mock.patch.object(rust_uprev, 'ebuild_actions')
  def test_update_manifest(self, mock_run, mock_flip):
    ebuild_file = Path('/path/to/rust/rust-1.1.1.ebuild')
    rust_uprev.update_manifest(ebuild_file)
    mock_run.assert_called_once_with('rust', ['manifest'])
    mock_flip.assert_has_calls(
        [mock.call(ebuild_file, add=True),
         mock.call(ebuild_file, add=False)])


class UpdateBootstrapEbuildTest(unittest.TestCase):
  """Tests for rust_uprev.update_bootstrap_ebuild()"""

  def test_update_bootstrap_ebuild(self):
    # The update should do two things:
    # 1. Create a copy of rust-bootstrap's ebuild with the new version number.
    # 2. Add the old PV to RUSTC_RAW_FULL_BOOTSTRAP_SEQUENCE.
    with tempfile.TemporaryDirectory() as tmpdir_str, \
         mock.patch.object(rust_uprev, 'find_ebuild_path') as mock_find_ebuild:
      tmpdir = Path(tmpdir_str)
      bootstrapdir = Path.joinpath(tmpdir, 'rust-bootstrap')
      bootstrapdir.mkdir()
      old_ebuild = bootstrapdir.joinpath('rust-bootstrap-1.45.2.ebuild')
      old_ebuild.write_text(encoding='utf-8',
                            data="""
some text
RUSTC_RAW_FULL_BOOTSTRAP_SEQUENCE=(
\t1.43.1
\t1.44.1
)
some more text
""")
      mock_find_ebuild.return_value = old_ebuild
      rust_uprev.update_bootstrap_ebuild(rust_uprev.RustVersion(1, 46, 0))
      new_ebuild = bootstrapdir.joinpath('rust-bootstrap-1.46.0.ebuild')
      self.assertTrue(new_ebuild.exists())
      text = new_ebuild.read_text()
      self.assertEqual(
          text, """
some text
RUSTC_RAW_FULL_BOOTSTRAP_SEQUENCE=(
\t1.43.1
\t1.44.1
\t1.45.2
)
some more text
""")


class UpdateRustPackagesTests(unittest.TestCase):
  """Tests for update_rust_packages step."""

  def setUp(self):
    self.old_version = rust_uprev.RustVersion(1, 1, 0)
    self.current_version = rust_uprev.RustVersion(1, 2, 3)
    self.new_version = rust_uprev.RustVersion(1, 3, 5)
    self.ebuild_file = os.path.join(rust_uprev.RUST_PATH,
                                    'rust-{self.new_version}.ebuild')

  def test_add_new_rust_packages(self):
    package_before = (f'dev-lang/rust-{self.old_version}\n'
                      f'dev-lang/rust-{self.current_version}')
    package_after = (f'dev-lang/rust-{self.old_version}\n'
                     f'dev-lang/rust-{self.current_version}\n'
                     f'dev-lang/rust-{self.new_version}')
    mock_open = mock.mock_open(read_data=package_before)
    with mock.patch('builtins.open', mock_open):
      rust_uprev.update_rust_packages(self.new_version, add=True)
    mock_open.return_value.__enter__().write.assert_called_once_with(
        package_after)

  def test_remove_old_rust_packages(self):
    package_before = (f'dev-lang/rust-{self.old_version}\n'
                      f'dev-lang/rust-{self.current_version}\n'
                      f'dev-lang/rust-{self.new_version}')
    package_after = (f'dev-lang/rust-{self.current_version}\n'
                     f'dev-lang/rust-{self.new_version}')
    mock_open = mock.mock_open(read_data=package_before)
    with mock.patch('builtins.open', mock_open):
      rust_uprev.update_rust_packages(self.old_version, add=False)
    mock_open.return_value.__enter__().write.assert_called_once_with(
        package_after)


class RustUprevOtherStagesTests(unittest.TestCase):
  """Tests for other steps in rust_uprev"""

  def setUp(self):
    self.old_version = rust_uprev.RustVersion(1, 1, 0)
    self.current_version = rust_uprev.RustVersion(1, 2, 3)
    self.new_version = rust_uprev.RustVersion(1, 3, 5)
    self.ebuild_file = os.path.join(rust_uprev.RUST_PATH,
                                    'rust-{self.new_version}.ebuild')

  @mock.patch.object(shutil, 'copyfile')
  @mock.patch.object(os, 'listdir')
  @mock.patch.object(subprocess, 'check_call')
  def test_copy_patches(self, mock_call, mock_ls, mock_copy):
    mock_ls.return_value = [
        f'rust-{self.old_version}-patch-1.patch',
        f'rust-{self.old_version}-patch-2-old.patch',
        f'rust-{self.current_version}-patch-1.patch',
        f'rust-{self.current_version}-patch-2-new.patch'
    ]
    rust_uprev.copy_patches(rust_uprev.RUST_PATH, self.current_version,
                            self.new_version)
    mock_copy.assert_has_calls([
        mock.call(
            os.path.join(rust_uprev.RUST_PATH, 'files',
                         f'rust-{self.current_version}-patch-1.patch'),
            os.path.join(rust_uprev.RUST_PATH, 'files',
                         f'rust-{self.new_version}-patch-1.patch'),
        ),
        mock.call(
            os.path.join(rust_uprev.RUST_PATH, 'files',
                         f'rust-{self.current_version}-patch-2-new.patch'),
            os.path.join(rust_uprev.RUST_PATH, 'files',
                         f'rust-{self.new_version}-patch-2-new.patch'))
    ])
    mock_call.assert_called_once_with(
        ['git', 'add', f'rust-{self.new_version}-*.patch'],
        cwd=rust_uprev.RUST_PATH.joinpath('files'))

  @mock.patch.object(shutil, 'copyfile')
  @mock.patch.object(subprocess, 'check_call')
  def test_create_ebuild(self, mock_call, mock_copy):
    template_ebuild = f'/path/to/rust-{self.current_version}-r2.ebuild'
    rust_uprev.create_ebuild(template_ebuild, self.new_version)
    mock_copy.assert_called_once_with(
        template_ebuild,
        rust_uprev.RUST_PATH.joinpath(f'rust-{self.new_version}.ebuild'))
    mock_call.assert_called_once_with(
        ['git', 'add', f'rust-{self.new_version}.ebuild'],
        cwd=rust_uprev.RUST_PATH)

  @mock.patch.object(rust_uprev, 'find_ebuild_for_package')
  @mock.patch.object(subprocess, 'check_call')
  def test_remove_rust_bootstrap_version(self, mock_call, *_args):
    bootstrap_path = os.path.join(rust_uprev.RUST_PATH, '..', 'rust-bootstrap')
    rust_uprev.remove_rust_bootstrap_version(self.old_version, lambda *x: ())
    mock_call.has_calls([
        [
            'git', 'rm',
            os.path.join(bootstrap_path, 'files',
                         f'rust-bootstrap-{self.old_version}-*.patch')
        ],
        [
            'git', 'rm',
            os.path.join(bootstrap_path,
                         f'rust-bootstrap-{self.old_version}.ebuild')
        ],
    ])

  @mock.patch.object(rust_uprev, 'find_ebuild_path')
  @mock.patch.object(subprocess, 'check_call')
  def test_remove_virtual_rust(self, mock_call, mock_find_ebuild):
    ebuild_path = Path(
        f'/some/dir/virtual/rust/rust-{self.old_version}.ebuild')
    mock_find_ebuild.return_value = Path(ebuild_path)
    rust_uprev.remove_virtual_rust(self.old_version)
    mock_call.assert_called_once_with(
        ['git', 'rm', str(ebuild_path.name)], cwd=ebuild_path.parent)

  @mock.patch.object(rust_uprev, 'find_ebuild_path')
  @mock.patch.object(shutil, 'copyfile')
  @mock.patch.object(subprocess, 'check_call')
  def test_update_virtual_rust(self, mock_call, mock_copy, mock_find_ebuild):
    ebuild_path = Path(
        f'/some/dir/virtual/rust/rust-{self.current_version}.ebuild')
    mock_find_ebuild.return_value = Path(ebuild_path)
    rust_uprev.update_virtual_rust(self.current_version, self.new_version)
    mock_call.assert_called_once_with(
        ['git', 'add', f'rust-{self.new_version}.ebuild'],
        cwd=ebuild_path.parent)
    mock_copy.assert_called_once_with(
        ebuild_path.parent.joinpath(f'rust-{self.current_version}.ebuild'),
        ebuild_path.parent.joinpath(f'rust-{self.new_version}.ebuild'))

  @mock.patch.object(os, 'listdir')
  def test_find_oldest_rust_version_in_chroot_pass(self, mock_ls):
    oldest_version_name = f'rust-{self.old_version}.ebuild'
    mock_ls.return_value = [
        oldest_version_name, f'rust-{self.current_version}.ebuild',
        f'rust-{self.new_version}.ebuild'
    ]
    actual = rust_uprev.find_oldest_rust_version_in_chroot()
    expected = (self.old_version,
                os.path.join(rust_uprev.RUST_PATH, oldest_version_name))
    self.assertEqual(expected, actual)

  @mock.patch.object(os, 'listdir')
  def test_find_oldest_rust_version_in_chroot_fail_with_only_one_ebuild(
      self, mock_ls):
    mock_ls.return_value = [f'rust-{self.new_version}.ebuild']
    with self.assertRaises(RuntimeError) as context:
      rust_uprev.find_oldest_rust_version_in_chroot()
    self.assertEqual('Expect to find more than one Rust versions',
                     str(context.exception))

  @mock.patch.object(rust_uprev, 'get_command_output')
  @mock.patch.object(git, 'CreateBranch')
  def test_create_new_repo(self, mock_branch, mock_output):
    mock_output.return_value = ''
    rust_uprev.create_new_repo(self.new_version)
    mock_branch.assert_called_once_with(rust_uprev.RUST_PATH,
                                        f'rust-to-{self.new_version}')

  @mock.patch.object(rust_uprev, 'get_command_output')
  @mock.patch.object(subprocess, 'check_call')
  def test_build_cross_compiler(self, mock_call, mock_output):
    mock_output.return_value = f'rust-{self.new_version}.ebuild'
    cros_targets = [
        'x86_64-cros-linux-gnu',
        'armv7a-cros-linux-gnueabihf',
        'aarch64-cros-linux-gnu',
    ]
    all_triples = ['x86_64-pc-linux-gnu'] + cros_targets
    rust_ebuild = 'RUSTC_TARGET_TRIPLES=(' + '\n\t'.join(all_triples) + ')'
    mock_open = mock.mock_open(read_data=rust_ebuild)
    with mock.patch('builtins.open', mock_open):
      rust_uprev.build_cross_compiler()

    mock_call.assert_called_once_with(
        ['sudo', 'emerge', '-j', '-G'] +
        [f'cross-{x}/gcc' for x in cros_targets + ['arm-none-eabi']])


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