# 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 tricium_clang_tidy.py."""

import io
import json
import multiprocessing
import os
from pathlib import Path
import subprocess
import sys
import tempfile
from typing import NamedTuple
from unittest import mock

from chromite.lib import cros_test_lib
from chromite.lib import osutils
from chromite.scripts import tricium_clang_tidy

assert sys.version_info >= (3, 6), 'This module requires Python 3.6+'


class Replacement(NamedTuple):
  """A YAML `tricium_clang_tidy.TidyReplacement`.

  The data contained in YAML is slightly different than what `TidyReplacement`s
  carry.
  """
  file_path: str
  text: str
  offset: int
  length: int


class Note(NamedTuple):
  """A clang-tidy `note` from the YAML file."""
  message: str
  file_path: str
  file_offset: int


def default_tidy_diagnostic(file_path='/tidy/file.c',
                            line_number=1,
                            diag_name='${diag_name}',
                            message='${message}',
                            replacements=(),
                            expansion_locs=()):
  """Creates a TidyDiagnostic with reasonable defaults.

  Defaults here and yaml_diagnostic are generally intended to match where
  possible.
  """
  return tricium_clang_tidy.TidyDiagnostic(
      file_path=file_path,
      line_number=line_number,
      diag_name=diag_name,
      message=message,
      replacements=replacements,
      expansion_locs=expansion_locs)


def yaml_diagnostic(name='${diag_name}',
                    message='${message}',
                    file_path='/tidy/file.c',
                    file_offset=1,
                    replacements=(),
                    notes=()):
  """Creates a diagnostic serializable as YAML with reasonable defaults."""
  result = {
      'DiagnosticName': name,
      'DiagnosticMessage': {
          'Message': message,
          'FilePath': file_path,
          'FileOffset': file_offset,
      },
  }

  if replacements:
    result['DiagnosticMessage']['Replacements'] = [{
        'FilePath': x.file_path,
        'Offset': x.offset,
        'Length': x.length,
        'ReplacementText': x.text,
    } for x in replacements]

  if notes:
    result['Notes'] = [{
        'Message': x.message,
        'FilePath': x.file_path,
        'FileOffset': x.file_offset,
    } for x in notes]

  return result


def mocked_nop_realpath(f):
  """Mocks os.path.realpath to just return its argument."""

  @mock.patch.object(os.path, 'realpath')
  @mock.patch.object(Path, 'resolve')
  def inner(self, replace_mock, realpath_mock, *args, **kwargs):
    """Mocker for realpath."""
    identity = lambda x: x
    realpath_mock.side_effect = identity
    replace_mock.side_effect = identity
    return f(self, *args, **kwargs)

  return inner


def mocked_readonly_open(contents=None, default=None):
  """Mocks out open() so it always returns things from |contents|.

  Writing to open'ed files is not supported.

  Args:
    contents: a |dict| mapping |file_path| => file_contents.
    default: a default string to return if the given |file_path| doesn't
      exist in |contents|.

  Returns:
    |contents[file_path]| if it exists; otherwise, |default|.

  Raises:
    If |default| is None and |contents[file_path]| does not exist, this will
    raise a |ValueError|.
  """

  if contents is None:
    contents = {}

  def inner(f):
    """mocked_open impl."""

    @mock.mock_open()
    def inner_inner(self, open_mock, *args, **kwargs):
      """the impl of mocked_readonly_open's impl!"""

      def get_data(file_path, mode='r', encoding=None):
        """the impl of the impl of mocked_readonly_open's impl!!"""
        data = contents.get(file_path, default)
        if data is None:
          raise ValueError('No %r file was found; options were %r' %
                           (file_path, sorted(contents.keys())))

        assert mode == 'r', f"File mode {mode} isn't supported."
        if encoding is None:
          return io.BytesIO(data)
        return io.StringIO(data)

      open_mock.side_effect = get_data

      def get_data_stream(file_path):
        return io.StringIO(get_data(file_path))

      open_mock.side_effect = get_data_stream
      return f(self, *args, **kwargs)

    return inner_inner

  return inner


class TriciumClangTidyTests(cros_test_lib.MockTestCase):
  """Various tests for tricium support."""

  def test_tidy_diagnostic_path_normalization(self):
    expanded_from = tricium_clang_tidy.TidyExpandedFrom(
        file_path=Path('/old2/foo'),
        line_number=2,
    )
    diag = default_tidy_diagnostic(
        file_path=Path('/old/foo'),
        expansion_locs=(expanded_from,),
    )

    normalized = diag.normalize_paths_to('/new')
    self.assertEqual(
        normalized,
        diag._replace(
            file_path=Path('../old/foo'),
            expansion_locs=(expanded_from._replace(
                file_path=Path('../old2/foo')),),
        ),
    )

  def test_line_offest_map_works(self):
    # (input_char, line_number_of_char, line_offset_of_char)
    line_offset_pairs = [
        ('a', 1, 0),
        ('b', 1, 1),
        ('\n', 1, 2),
        ('c', 2, 0),
        ('\n', 2, 1),
        ('\n', 3, 0),
        ('d', 4, 0),
        ('', 4, 1),
        ('', 4, 2),
    ]
    text = tricium_clang_tidy.LineOffsetMap.for_text(''.join(
        x for x, _, _ in line_offset_pairs))
    for offset, (_, line_number, line_offset) in enumerate(line_offset_pairs):
      self.assertEqual(text.get_line_number(offset), line_number)
      self.assertEqual(text.get_line_offset(offset), line_offset)

  def test_package_ebuild_resolution(self):
    run_mock = self.StartPatcher(cros_test_lib.RunCommandMock())
    run_mock.SetDefaultCmdResult(stdout='${package1_ebuild}\n')
    ebuilds = tricium_clang_tidy.resolve_package_ebuilds(
        '${board}',
        [
            'package1',
            'package2.ebuild',
        ],
    )

    run_mock.assertCommandContains(['equery-${board}', 'w', 'package1'],
                                   check=True,
                                   stdout=subprocess.PIPE,
                                   encoding='utf-8')
    self.assertEqual(ebuilds, ['${package1_ebuild}', 'package2.ebuild'])

  @mocked_readonly_open(default='')
  def test_parse_tidy_invocation_returns_exception_on_error(
      self, read_file_mock):
    oh_no = ValueError('${oh_no}!')
    read_file_mock.side_effect = oh_no
    result = tricium_clang_tidy.parse_tidy_invocation(
        Path('/some/file/that/doesnt/exist.json'))
    self.assertIn(str(oh_no), str(result))

  @mocked_readonly_open({
      '/file/path.json':
          json.dumps({
              'exit_code': 1,
              'executable': '${clang_tidy}',
              'args': ['foo', 'bar'],
              'lint_target': '${target}',
              'stdstreams': 'brrrrrrr',
              'wd': '/path/to/wd',
          }),
      # |yaml.dumps| doesn't exist, but json parses cleanly as yaml, so...
      '/file/path.yaml':
          json.dumps({
              'Diagnostics': [
                  yaml_diagnostic(
                      name='some-diag',
                      message='${message}',
                      file_path='',
                  ),
              ]
          }),
  })
  def test_parse_tidy_invocation_functions_on_success(self):
    result = tricium_clang_tidy.parse_tidy_invocation('/file/path.json')
    # If we got an |Exception|, print it out.
    self.assertFalse(isinstance(result, tricium_clang_tidy.Error), result)
    meta, info = result
    self.assertEqual(
        meta,
        tricium_clang_tidy.InvocationMetadata(
            exit_code=1,
            invocation=['${clang_tidy}', 'foo', 'bar'],
            lint_target='${target}',
            stdstreams='brrrrrrr',
            wd='/path/to/wd',
        ),
    )

    self.assertEqual(
        info,
        [
            default_tidy_diagnostic(
                diag_name='some-diag',
                message='${message}',
                file_path='',
            ),
        ],
    )

  @mocked_nop_realpath
  @mocked_readonly_open(default='')
  def test_parse_fixes_file_absolutizes_paths(self):
    results = tricium_clang_tidy.parse_tidy_fixes_file(
        '/tidy', {
            'Diagnostics': [
                yaml_diagnostic(file_path='foo.c'),
                yaml_diagnostic(file_path='/tidy/bar.c'),
                yaml_diagnostic(file_path=''),
            ],
        })
    file_paths = [x.file_path for x in results]
    self.assertEqual(file_paths, ['/tidy/foo.c', '/tidy/bar.c', ''])

  @mocked_nop_realpath
  @mocked_readonly_open({
      '/tidy/foo.c': '',
      '/tidy/foo.h': 'a\n\n',
  })
  def test_parse_fixes_file_interprets_offsets_correctly(self):
    results = tricium_clang_tidy.parse_tidy_fixes_file(
        '/tidy', {
            'Diagnostics': [
                yaml_diagnostic(file_path='/tidy/foo.c', file_offset=1),
                yaml_diagnostic(file_path='/tidy/foo.c', file_offset=2),
                yaml_diagnostic(file_path='/tidy/foo.h', file_offset=1),
                yaml_diagnostic(file_path='/tidy/foo.h', file_offset=2),
                yaml_diagnostic(file_path='/tidy/foo.h', file_offset=3),
            ],
        })
    file_locations = [(x.file_path, x.line_number) for x in results]
    self.assertEqual(file_locations, [
        ('/tidy/foo.c', 1),
        ('/tidy/foo.c', 1),
        ('/tidy/foo.h', 1),
        ('/tidy/foo.h', 2),
        ('/tidy/foo.h', 3),
    ])

  @mocked_nop_realpath
  @mocked_readonly_open({'/tidy/foo.c': 'a \n\n'})
  def test_parse_fixes_file_handles_replacements(self):
    results = list(
        tricium_clang_tidy.parse_tidy_fixes_file(
            '/tidy', {
                'Diagnostics': [
                    yaml_diagnostic(
                        file_path='/tidy/foo.c',
                        file_offset=1,
                        replacements=[
                            Replacement(
                                file_path='foo.c',
                                text='whee',
                                offset=2,
                                length=2,
                            ),
                        ],
                    ),
                ],
            }))
    self.assertEqual(len(results), 1, results)
    self.assertEqual(
        results[0].replacements,
        (tricium_clang_tidy.TidyReplacement(
            new_text='whee',
            start_line=1,
            end_line=3,
            start_char=2,
            end_char=0,
        ),),
    )

  @mocked_nop_realpath
  @mocked_readonly_open({'/whee.c': '', '/whee.h': '\n\n'})
  def test_parse_fixes_file_handles_macro_expansions(self):
    results = list(
        tricium_clang_tidy.parse_tidy_fixes_file(
            '/tidy', {
                'Diagnostics': [
                    yaml_diagnostic(
                        file_path='/whee.c',
                        file_offset=1,
                        notes=[
                            Note(
                                message='not relevant',
                                file_path='/whee.c',
                                file_offset=1,
                            ),
                            Note(
                                message='expanded from macro "Foo"',
                                file_path='/whee.h',
                                file_offset=9,
                            ),
                        ],
                    ),
                ],
            }))
    self.assertEqual(len(results), 1, results)
    self.assertEqual(
        results[0].expansion_locs,
        (tricium_clang_tidy.TidyExpandedFrom(
            file_path='/whee.h',
            line_number=3,
        ),),
    )

  @mock.patch.object(Path, 'glob')
  @mock.patch.object(tricium_clang_tidy, 'parse_tidy_invocation')
  def test_collect_lints_functions(self, parse_invocation_mock, glob_mock):
    glob_mock.return_value = ('/lint/foo.json', '/lint/bar.json')

    diag_1 = default_tidy_diagnostic()
    diag_2 = diag_1._replace(line_number=diag_1.line_number + 1)
    diag_3 = diag_2._replace(line_number=diag_2.line_number + 1)

    # Because we want to test unique'ing, ensure these aren't equal.
    all_diags = [diag_1, diag_2, diag_3]
    self.assertEqual(sorted(all_diags), sorted(set(all_diags)))

    per_file_lints = {
        '/lint/foo.json': {diag_1, diag_2},
        '/lint/bar.json': {diag_2, diag_3},
    }

    def parse_invocation_side_effect(json_file):
      self.assertIn(json_file, per_file_lints)
      meta = mock.Mock()
      meta.exit_code = 0
      return meta, per_file_lints[json_file]

    parse_invocation_mock.side_effect = parse_invocation_side_effect

    with multiprocessing.pool.ThreadPool(1) as yaml_pool:
      lints = tricium_clang_tidy.collect_lints(Path('/lint'), yaml_pool)

    self.assertEqual(set(all_diags), lints)

  def test_filter_tidy_lints_filters_nothing_by_default(self):
    basis = default_tidy_diagnostic()
    diag2 = default_tidy_diagnostic(line_number=basis.line_number + 1)
    diags = [basis, diag2]
    diags.sort()

    self.assertEqual(
        diags,
        tricium_clang_tidy.filter_tidy_lints(
            only_files=None,
            git_repo_base=None,
            diags=diags,
        ),
    )

  def test_filter_tidy_lints_filters_paths_outside_of_only_files(self):
    in_only_files = default_tidy_diagnostic(file_path='foo.c')
    out_of_only_files = default_tidy_diagnostic(file_path='bar.c')
    self.assertEqual(
        [in_only_files],
        tricium_clang_tidy.filter_tidy_lints(
            only_files={Path('foo.c')},
            git_repo_base=None,
            diags=[in_only_files, out_of_only_files],
        ),
    )

  def test_filter_tidy_lints_normalizes_to_git_repo_baes(self):
    git = default_tidy_diagnostic(file_path='/git/foo.c')
    nogit = default_tidy_diagnostic(file_path='/nogit/bar.c')
    self.assertEqual(
        [git.normalize_paths_to('/git')],
        tricium_clang_tidy.filter_tidy_lints(
            only_files=None,
            git_repo_base=Path('/git'),
            diags=[git, nogit],
        ),
    )

  def test_filter_tidy_lints_normalizes_and_restricts_properly(self):
    git_and_only = default_tidy_diagnostic(file_path='/git/foo.c')
    git_and_noonly = default_tidy_diagnostic(file_path='/git/bar.c')
    self.assertEqual(
        [git_and_only.normalize_paths_to('/git')],
        tricium_clang_tidy.filter_tidy_lints(
            only_files={Path('/git/foo.c')},
            git_repo_base=Path('/git'),
            diags=[git_and_only, git_and_noonly],
        ),
    )

  @mock.patch.object(osutils, 'CopyDirContents')
  @mock.patch.object(osutils, 'SafeMakedirs')
  @mock.patch.object(osutils, 'RmDir')
  def test_lint_generation_functions(self, rmdir_mock, safe_makedirs_mock,
                                     copy_dir_contents_mock):
    run_mock = self.StartPatcher(cros_test_lib.PopenMock())
    run_mock.SetDefaultCmdResult()

    # Mock mkdtemp last, since PopenMock() makes a tempdir.
    mkdtemp_mock = self.PatchObject(tempfile, 'mkdtemp')
    mkdtemp_path = '/path/to/temp/dir'
    mkdtemp_mock.return_value = mkdtemp_path
    dir_name = str(
        tricium_clang_tidy.generate_lints('${board}', '/path/to/the.ebuild'))
    self.assertEqual(mkdtemp_path, dir_name)

    rmdir_mock.assert_called_with(
        tricium_clang_tidy.LINT_BASE, ignore_missing=True, sudo=True)
    safe_makedirs_mock.assert_called_with(
        tricium_clang_tidy.LINT_BASE, 0o777, sudo=True)

    desired_env = dict(os.environ)
    desired_env['WITH_TIDY'] = 'tricium'
    run_mock.assertCommandContains(
        ['ebuild-${board}', '/path/to/the.ebuild', 'clean', 'compile'],
        env=desired_env)

    copy_dir_contents_mock.assert_called_with(tricium_clang_tidy.LINT_BASE,
                                              dir_name)
