#!/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_watch.py."""

import logging
import pathlib
import subprocess
import time
import unittest
import unittest.mock

from cros_utils import tiny_render

import rust_watch


class Test(unittest.TestCase):
  """Tests."""
  def _silence_logs(self):
    """Silences all log output until the end of the current test."""
    def should_log(_record):
      return 0

    logger = logging.root
    logger.addFilter(should_log)
    self.addCleanup(logger.removeFilter, should_log)

  def test_release_version_parsing(self):
    self.assertEqual(
        rust_watch.RustReleaseVersion.from_string('1.2.3'),
        rust_watch.RustReleaseVersion(1, 2, 3),
    )

  def test_release_version_json_round_trips(self):
    ver = rust_watch.RustReleaseVersion(1, 2, 3)
    self.assertEqual(rust_watch.RustReleaseVersion.from_json(ver.to_json()),
                     ver)

  def test_state_json_round_trips(self):
    state = rust_watch.State(
        last_seen_release=rust_watch.RustReleaseVersion(1, 2, 3),
        last_gentoo_sha='abc123',
    )

    self.assertEqual(rust_watch.State.from_json(state.to_json()), state)

  @unittest.mock.patch.object(subprocess, 'run')
  @unittest.mock.patch.object(time, 'sleep')
  def test_update_git_repo_tries_again_on_failure(self, sleep_mock, run_mock):
    self._silence_logs()

    oh_no_error = ValueError('oh no')

    def check_returncode():
      raise oh_no_error

    run_call_count = 0

    def run_sideeffect(*_args, **_kwargs):
      nonlocal run_call_count
      run_call_count += 1
      result = unittest.mock.Mock()
      result.returncode = 1
      result.check_returncode = check_returncode
      return result

    run_mock.side_effect = run_sideeffect

    with self.assertRaises(ValueError) as raised:
      rust_watch.update_git_repo(pathlib.Path('/does/not/exist/at/all'))

    self.assertIs(raised.exception, oh_no_error)
    self.assertEqual(run_call_count, 5)

    sleep_timings = [unittest.mock.call(60 * i) for i in range(1, 5)]
    self.assertEqual(sleep_mock.mock_calls, sleep_timings)

  @unittest.mock.patch.object(subprocess, 'run')
  def test_get_new_gentoo_commits_functions(self, run_mock):
    returned = unittest.mock.Mock()
    returned.returncode = 0
    returned.stdout = '\n'.join((
        'abc123 newer commit',
        'abcdef and an older commit',
    ))
    run_mock.return_value = returned
    results = rust_watch.get_new_gentoo_commits(
        pathlib.Path('/does/not/exist/at/all'), 'defabc')
    self.assertEqual(results, [
        rust_watch.GitCommit('abcdef', 'and an older commit'),
        rust_watch.GitCommit('abc123', 'newer commit'),
    ])

  def test_compose_email_on_a_new_gentoo_commit(self):
    sha_a = 'a' * 40
    new_commit = rust_watch.maybe_compose_email(new_gentoo_commits=[
        rust_watch.GitCommit(
            sha=sha_a,
            subject='summary_a',
        ),
    ], )

    self.assertEqual(new_commit,
                     ('[rust-watch] new rust ebuild commit detected', [
                         'commit:',
                         tiny_render.UnorderedList([
                             [
                                 tiny_render.Link(
                                     rust_watch.gentoo_sha_to_link(sha_a),
                                     sha_a[:12],
                                 ),
                                 ': summary_a',
                             ],
                         ])
                     ]))

  def test_compose_email_composes_nothing_when_no_new_updates_exist(self):
    self.assertIsNone(rust_watch.maybe_compose_email(new_gentoo_commits=()))

  def test_compose_bug_creates_bugs_on_new_versions(self):
    title, body = rust_watch.maybe_compose_bug(
        old_state=rust_watch.State(
            last_seen_release=rust_watch.RustReleaseVersion(1, 0, 0),
            last_gentoo_sha='',
        ),
        newest_release=rust_watch.RustReleaseVersion(1, 0, 1),
    )
    self.assertEqual(title, '[Rust] Update to 1.0.1')
    self.assertTrue(body.startswith('A new release has been detected;'))

    title, body = rust_watch.maybe_compose_bug(
        old_state=rust_watch.State(
            last_seen_release=rust_watch.RustReleaseVersion(1, 0, 0),
            last_gentoo_sha='',
        ),
        newest_release=rust_watch.RustReleaseVersion(1, 1, 0),
    )
    self.assertEqual(title, '[Rust] Update to 1.1.0')
    self.assertTrue(body.startswith('A new release has been detected;'))

    title, body = rust_watch.maybe_compose_bug(
        old_state=rust_watch.State(
            last_seen_release=rust_watch.RustReleaseVersion(1, 0, 0),
            last_gentoo_sha='',
        ),
        newest_release=rust_watch.RustReleaseVersion(2, 0, 0),
    )
    self.assertEqual(title, '[Rust] Update to 2.0.0')
    self.assertTrue(body.startswith('A new release has been detected;'))

  def test_compose_bug_does_nothing_when_no_new_updates_exist(self):
    self.assertIsNone(
        rust_watch.maybe_compose_bug(
            old_state=rust_watch.State(
                last_seen_release=rust_watch.RustReleaseVersion(1, 0, 0),
                last_gentoo_sha='',
            ),
            newest_release=rust_watch.RustReleaseVersion(1, 0, 0),
        ))


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