# Copyright (c) 2003-2013 LOGILAB S.A. (Paris, FRANCE).
# http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
"""functional/non regression tests for pylint"""
from __future__ import print_function

import collections
import contextlib
import functools
import os
import sys
import re
import unittest
import tempfile
import tokenize

from glob import glob
from os import linesep, getcwd, sep
from os.path import abspath, basename, dirname, isdir, join, splitext

from astroid import test_utils

from pylint import checkers
from pylint.utils import PyLintASTWalker
from pylint.reporters import BaseReporter
from pylint.interfaces import IReporter
from pylint.lint import PyLinter

import six
from six.moves import StringIO


# Utils

SYS_VERS_STR = '%d%d%d' % sys.version_info[:3]
TITLE_UNDERLINES = ['', '=', '-', '.']
PREFIX = abspath(dirname(__file__))
PY3K = sys.version_info[0] == 3

def fix_path():
    sys.path.insert(0, PREFIX)

def get_tests_info(input_dir, msg_dir, prefix, suffix):
    """get python input examples and output messages

    We use following conventions for input files and messages:
    for different inputs:
        test for python  >= x.y    ->  input   =  <name>_pyxy.py
        test for python  <  x.y    ->  input   =  <name>_py_xy.py
    for one input and different messages:
        message for python >=  x.y ->  message =  <name>_pyxy.txt
        lower versions             ->  message with highest num
    """
    result = []
    for fname in glob(join(input_dir, prefix + '*' + suffix)):
        infile = basename(fname)
        fbase = splitext(infile)[0]
        # filter input files :
        pyrestr = fbase.rsplit('_py', 1)[-1] # like _26 or 26
        if pyrestr.isdigit(): # '24', '25'...
            if SYS_VERS_STR < pyrestr:
                continue
        if pyrestr.startswith('_') and  pyrestr[1:].isdigit():
            # skip test for higher python versions
            if SYS_VERS_STR >= pyrestr[1:]:
                continue
        messages = glob(join(msg_dir, fbase + '*.txt'))
        # the last one will be without ext, i.e. for all or upper versions:
        if messages:
            for outfile in sorted(messages, reverse=True):
                py_rest = outfile.rsplit('_py', 1)[-1][:-4]
                if py_rest.isdigit() and SYS_VERS_STR >= py_rest:
                    break
        else:
            # This will provide an error message indicating the missing filename.
            outfile = join(msg_dir, fbase + '.txt')
        result.append((infile, outfile))
    return result


class TestReporter(BaseReporter):
    """reporter storing plain text messages"""

    __implements____ = IReporter

    def __init__(self): # pylint: disable=super-init-not-called

        self.message_ids = {}
        self.reset()
        self.path_strip_prefix = getcwd() + sep

    def reset(self):
        self.out = StringIO()
        self.messages = []

    def add_message(self, msg_id, location, msg):
        """manage message of different type and in the context of path """
        _, _, obj, line, _ = location
        self.message_ids[msg_id] = 1
        if obj:
            obj = ':%s' % obj
        sigle = msg_id[0]
        if PY3K and linesep != '\n':
            # 2to3 writes os.linesep instead of using
            # the previosly used line separators
            msg = msg.replace('\r\n', '\n')
        self.messages.append('%s:%3s%s: %s' % (sigle, line, obj, msg))

    def finalize(self):
        self.messages.sort()
        for msg in self.messages:
            print(msg, file=self.out)
        result = self.out.getvalue()
        self.reset()
        return result

    def display_results(self, layout):
        """ignore layouts"""


class Message(collections.namedtuple('Message',
                                     ['msg_id', 'line', 'node', 'args'])):
    def __new__(cls, msg_id, line=None, node=None, args=None):
        return tuple.__new__(cls, (msg_id, line, node, args))


class UnittestLinter(object):
    """A fake linter class to capture checker messages."""
    # pylint: disable=unused-argument, no-self-use

    def __init__(self):
        self._messages = []
        self.stats = {}

    def release_messages(self):
        try:
            return self._messages
        finally:
            self._messages = []

    def add_message(self, msg_id, line=None, node=None, args=None,
                    confidence=None):
        self._messages.append(Message(msg_id, line, node, args))

    def is_message_enabled(self, *unused_args):
        return True

    def add_stats(self, **kwargs):
        for name, value in six.iteritems(kwargs):
            self.stats[name] = value
        return self.stats

    @property
    def options_providers(self):
        return linter.options_providers

def set_config(**kwargs):
    """Decorator for setting config values on a checker."""
    def _Wrapper(fun):
        @functools.wraps(fun)
        def _Forward(self):
            for key, value in six.iteritems(kwargs):
                setattr(self.checker.config, key, value)
            if isinstance(self, CheckerTestCase):
                # reopen checker in case, it may be interested in configuration change
                self.checker.open()
            fun(self)

        return _Forward
    return _Wrapper


class CheckerTestCase(unittest.TestCase):
    """A base testcase class for unittesting individual checker classes."""
    CHECKER_CLASS = None
    CONFIG = {}

    def setUp(self):
        self.linter = UnittestLinter()
        self.checker = self.CHECKER_CLASS(self.linter) # pylint: disable=not-callable
        for key, value in six.iteritems(self.CONFIG):
            setattr(self.checker.config, key, value)
        self.checker.open()

    @contextlib.contextmanager
    def assertNoMessages(self):
        """Assert that no messages are added by the given method."""
        with self.assertAddsMessages():
            yield

    @contextlib.contextmanager
    def assertAddsMessages(self, *messages):
        """Assert that exactly the given method adds the given messages.

        The list of messages must exactly match *all* the messages added by the
        method. Additionally, we check to see whether the args in each message can
        actually be substituted into the message string.
        """
        yield
        got = self.linter.release_messages()
        msg = ('Expected messages did not match actual.\n'
               'Expected:\n%s\nGot:\n%s' % ('\n'.join(repr(m) for m in messages),
                                            '\n'.join(repr(m) for m in got)))
        self.assertEqual(list(messages), got, msg)

    def walk(self, node):
        """recursive walk on the given node"""
        walker = PyLintASTWalker(linter)
        walker.add_checker(self.checker)
        walker.walk(node)


# Init
test_reporter = TestReporter()
linter = PyLinter()
linter.set_reporter(test_reporter)
linter.config.persistent = 0
checkers.initialize(linter)
linter.global_set_option('required-attributes', ('__revision__',))

if linesep != '\n':
    LINE_RGX = re.compile(linesep)
    def ulines(string):
        return LINE_RGX.sub('\n', string)
else:
    def ulines(string):
        return string

INFO_TEST_RGX = re.compile(r'^func_i\d\d\d\d$')

def exception_str(self, ex): # pylint: disable=unused-argument
    """function used to replace default __str__ method of exception instances"""
    return 'in %s\n:: %s' % (ex.file, ', '.join(ex.args))

# Test classes

class LintTestUsingModule(unittest.TestCase):
    INPUT_DIR = None
    DEFAULT_PACKAGE = 'input'
    package = DEFAULT_PACKAGE
    linter = linter
    module = None
    depends = None
    output = None
    _TEST_TYPE = 'module'
    maxDiff = None

    def shortDescription(self):
        values = {'mode' : self._TEST_TYPE,
                  'input': self.module,
                  'pkg':   self.package,
                  'cls':   self.__class__.__name__}

        if self.package == self.DEFAULT_PACKAGE:
            msg = '%(mode)s test of input file "%(input)s" (%(cls)s)'
        else:
            msg = '%(mode)s test of input file "%(input)s" in "%(pkg)s" (%(cls)s)'
        return msg % values

    def test_functionality(self):
        tocheck = [self.package+'.'+self.module]
        if self.depends:
            tocheck += [self.package+'.%s' % name.replace('.py', '')
                        for name, _ in self.depends]
        self._test(tocheck)

    def _check_result(self, got):
        self.assertMultiLineEqual(self._get_expected().strip()+'\n',
                                  got.strip()+'\n')

    def _test(self, tocheck):
        if INFO_TEST_RGX.match(self.module):
            self.linter.enable('I')
        else:
            self.linter.disable('I')
        try:
            self.linter.check(tocheck)
        except Exception as ex:
            # need finalization to restore a correct state
            self.linter.reporter.finalize()
            ex.file = tocheck
            print(ex)
            ex.__str__ = exception_str
            raise
        self._check_result(self.linter.reporter.finalize())

    def _has_output(self):
        return not self.module.startswith('func_noerror_')

    def _get_expected(self):
        if self._has_output() and self.output:
            with open(self.output, 'U') as fobj:
                return fobj.read().strip() + '\n'
        else:
            return ''

class LintTestUsingFile(LintTestUsingModule):

    _TEST_TYPE = 'file'

    def test_functionality(self):
        importable = join(self.INPUT_DIR, self.module)
        # python also prefers packages over simple modules.
        if not isdir(importable):
            importable += '.py'
        tocheck = [importable]
        if self.depends:
            tocheck += [join(self.INPUT_DIR, name) for name, _file in self.depends]
        self._test(tocheck)

class LintTestUpdate(LintTestUsingModule):

    _TEST_TYPE = 'update'

    def _check_result(self, got):
        if self._has_output():
            try:
                expected = self._get_expected()
            except IOError:
                expected = ''
            if got != expected:
                with open(self.output, 'w') as fobj:
                    fobj.write(got)

# Callback

def cb_test_gen(base_class):
    def call(input_dir, msg_dir, module_file, messages_file, dependencies):
        # pylint: disable=no-init
        class LintTC(base_class):
            module = module_file.replace('.py', '')
            output = messages_file
            depends = dependencies or None
            INPUT_DIR = input_dir
            MSG_DIR = msg_dir
        return LintTC
    return call

# Main function

def make_tests(input_dir, msg_dir, filter_rgx, callbacks):
    """generate tests classes from test info

    return the list of generated test classes
    """
    if filter_rgx:
        is_to_run = re.compile(filter_rgx).search
    else:
        is_to_run = lambda x: 1
    tests = []
    for module_file, messages_file in (
            get_tests_info(input_dir, msg_dir, 'func_', '')
    ):
        if not is_to_run(module_file) or module_file.endswith('.pyc'):
            continue
        base = module_file.replace('func_', '').replace('.py', '')

        dependencies = get_tests_info(input_dir, msg_dir, base, '.py')

        for callback in callbacks:
            test = callback(input_dir, msg_dir, module_file, messages_file,
                            dependencies)
            if test:
                tests.append(test)
    return tests

def tokenize_str(code):
    return list(tokenize.generate_tokens(StringIO(code).readline))

@contextlib.contextmanager
def create_tempfile(content=None):
    """Create a new temporary file.

    If *content* parameter is given, then it will be written
    in the temporary file, before passing it back.
    This is a context manager and should be used with a *with* statement.
    """
    # Can't use tempfile.NamedTemporaryFile here
    # because on Windows the file must be closed before writing to it,
    # see http://bugs.python.org/issue14243
    fd, tmp = tempfile.mkstemp()
    if content:
        if sys.version_info >= (3, 0):
            # erff
            os.write(fd, bytes(content, 'ascii'))
        else:
            os.write(fd, content)
    try:
        yield tmp
    finally:
        os.close(fd)
        os.remove(tmp)

@contextlib.contextmanager
def create_file_backed_module(code):
    """Create an astroid module for the given code, backed by a real file."""
    with create_tempfile() as temp:
        module = test_utils.build_module(code)
        module.file = temp
        yield module
