diff options
author | Karel Kočí <cynerd@email.cz> | 2016-06-30 16:03:25 +0200 |
---|---|---|
committer | Karel Kočí <cynerd@email.cz> | 2016-06-30 16:03:25 +0200 |
commit | e573b3020c032400eed60b649a2cbf55266e6bb0 (patch) | |
tree | 8f572394ac8433529c7a8e70d160a2fbe8268b4e /vim/bundle/YouCompleteMe/python/ycm/test_utils.py | |
parent | b8c667bd64b3edd38d56c63c5bd1db53a23b4499 (diff) | |
download | myconfigs-e573b3020c032400eed60b649a2cbf55266e6bb0.tar.gz myconfigs-e573b3020c032400eed60b649a2cbf55266e6bb0.tar.bz2 myconfigs-e573b3020c032400eed60b649a2cbf55266e6bb0.zip |
Add current configurations from old repository
Diffstat (limited to 'vim/bundle/YouCompleteMe/python/ycm/test_utils.py')
-rw-r--r-- | vim/bundle/YouCompleteMe/python/ycm/test_utils.py | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/vim/bundle/YouCompleteMe/python/ycm/test_utils.py b/vim/bundle/YouCompleteMe/python/ycm/test_utils.py new file mode 100644 index 0000000..3a16255 --- /dev/null +++ b/vim/bundle/YouCompleteMe/python/ycm/test_utils.py @@ -0,0 +1,201 @@ +# Copyright (C) 2011, 2012 Google Inc. +# +# This file is part of YouCompleteMe. +# +# YouCompleteMe 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 3 of the License, or +# (at your option) any later version. +# +# YouCompleteMe 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 YouCompleteMe. If not, see <http://www.gnu.org/licenses/>. + +from __future__ import unicode_literals +from __future__ import print_function +from __future__ import division +from __future__ import absolute_import +from future import standard_library +standard_library.install_aliases() +from builtins import * # noqa + +from mock import MagicMock +from hamcrest import assert_that, equal_to +import re +import sys +import nose +import functools + +from ycmd.utils import ToUnicode + + +BUFNR_REGEX = re.compile( r"^bufnr\('(.+)', ([0-9]+)\)$" ) +BUFWINNR_REGEX = re.compile( r"^bufwinnr\(([0-9]+)\)$" ) +BWIPEOUT_REGEX = re.compile( r"^(?:silent! )bwipeout!? ([0-9]+)$" ) + +# One-and only instance of mocked Vim object. The first 'import vim' that is +# executed binds the vim module to the instance of MagicMock that is created, +# and subsquent assignments to sys.modules[ 'vim' ] don't retrospectively +# update them. The result is that while running the tests, we must assign only +# one instance of MagicMock to sys.modules[ 'vim' ] and always return it. +# +# More explanation is available: +# https://github.com/Valloric/YouCompleteMe/pull/1694 +VIM_MOCK = MagicMock() + +# The default options which are only relevant to the client, not the server and +# thus are not part of default_options.json, but are required for a working +# YouCompleteMe or OmniCompleter object. +DEFAULT_CLIENT_OPTIONS = { + 'server_log_level': 'info', + 'extra_conf_vim_data': [], + 'show_diagnostics_ui': 1, + 'enable_diagnostic_signs': 1, + 'enable_diagnostic_highlighting': 0, + 'always_populate_location_list': 0, +} + + +def MockGetBufferNumber( buffer_filename ): + for buffer in VIM_MOCK.buffers: + if buffer[ 'filename' ] == buffer_filename: + return buffer[ 'number' ] + return -1 + + +def MockGetBufferWindowNumber( buffer_number ): + for buffer in VIM_MOCK.buffers: + if buffer[ 'number' ] == buffer_number and 'window' in buffer: + return buffer[ 'window' ] + return -1 + + +def MockVimEval( value ): + if value == "g:ycm_min_num_of_chars_for_completion": + return 0 + if value == "g:ycm_server_python_interpreter": + return '' + if value == "tempname()": + return '_TEMP_FILE_' + if value == "&previewheight": + # Default value from Vim + return 12 + + match = BUFNR_REGEX.search( value ) + if match: + return MockGetBufferNumber( match.group( 1 ) ) + + match = BUFWINNR_REGEX.search( value ) + if match: + return MockGetBufferWindowNumber( int( match.group( 1 ) ) ) + + raise ValueError( 'Unexpected evaluation: ' + value ) + + +def MockWipeoutBuffer( buffer_number ): + buffers = VIM_MOCK.buffers + + for index, buffer in enumerate( buffers ): + if buffer[ 'number' ] == buffer_number: + return buffers.pop( index ) + + +def MockVimCommand( command ): + match = BWIPEOUT_REGEX.search( command ) + if match: + return MockWipeoutBuffer( int( match.group( 1 ) ) ) + + raise RuntimeError( 'Unexpected command: ' + command ) + + +def MockVimModule(): + """The 'vim' module is something that is only present when running inside the + Vim Python interpreter, so we replace it with a MagicMock for tests. If you + need to add additional mocks to vim module functions, then use 'patch' from + mock module, to ensure that the state of the vim mock is returned before the + next test. That is: + + from ycm.test_utils import MockVimModule + from mock import patch + + # Do this once + MockVimModule() + + @patch( 'vim.eval', return_value='test' ) + @patch( 'vim.command', side_effect=ValueError ) + def test( vim_command, vim_eval ): + # use vim.command via vim_command, e.g.: + vim_command.assert_has_calls( ... ) + + Failure to use this approach may lead to unexpected failures in other + tests.""" + + VIM_MOCK.buffers = {} + VIM_MOCK.eval = MagicMock( side_effect = MockVimEval ) + sys.modules[ 'vim' ] = VIM_MOCK + + return VIM_MOCK + + +class ExtendedMock( MagicMock ): + """An extension to the MagicMock class which adds the ability to check that a + callable is called with a precise set of calls in a precise order. + + Example Usage: + from ycm.test_utils import ExtendedMock + @patch( 'test.testing', new_callable = ExtendedMock, ... ) + def my_test( test_testing ): + ... + """ + + def assert_has_exact_calls( self, calls, any_order = False ): + self.assert_has_calls( calls, any_order ) + assert_that( self.call_count, equal_to( len( calls ) ) ) + + +def ExpectedFailure( reason, *exception_matchers ): + """Defines a decorator to be attached to tests. This decorator + marks the test as being known to fail, e.g. where documenting or exercising + known incorrect behaviour. + + The parameters are: + - |reason| a textual description of the reason for the known issue. This + is used for the skip reason + - |exception_matchers| additional arguments are hamcrest matchers to apply + to the exception thrown. If the matchers don't match, then the + test is marked as error, with the original exception. + + If the test fails (for the correct reason), then it is marked as skipped. + If it fails for any other reason, it is marked as failed. + If the test passes, then it is also marked as failed.""" + def decorator( test ): + @functools.wraps( test ) + def Wrapper( *args, **kwargs ): + try: + test( *args, **kwargs ) + except Exception as test_exception: + # Ensure that we failed for the right reason + test_exception_message = ToUnicode( test_exception ) + try: + for matcher in exception_matchers: + assert_that( test_exception_message, matcher ) + except AssertionError: + # Failed for the wrong reason! + import traceback + print( 'Test failed for the wrong reason: ' + traceback.format_exc() ) + # Real failure reason is the *original* exception, we're only trapping + # and ignoring the exception that is expected. + raise test_exception + + # Failed for the right reason + raise nose.SkipTest( reason ) + else: + raise AssertionError( 'Test was expected to fail: {0}'.format( + reason ) ) + return Wrapper + + return decorator |