Add tests for current directory

This commit is contained in:
micbou 2016-10-12 00:05:24 +02:00
parent ddf18cc6ec
commit 3109c9d8a4
No known key found for this signature in database
GPG Key ID: C7E8FD1F3BDA1E05
6 changed files with 211 additions and 54 deletions

View File

@ -27,6 +27,7 @@ from ycm.tests.test_utils import MockVimModule
MockVimModule() MockVimModule()
import functools import functools
import os
import requests import requests
import time import time
@ -48,6 +49,11 @@ DEFAULT_CLIENT_OPTIONS = {
} }
def PathToTestFile( *args ):
dir_of_current_script = os.path.dirname( os.path.abspath( __file__ ) )
return os.path.join( dir_of_current_script, 'testdata', *args )
def _MakeUserOptions( custom_options = {} ): def _MakeUserOptions( custom_options = {} ):
options = dict( user_options_store.DefaultOptions() ) options = dict( user_options_store.DefaultOptions() )
options.update( DEFAULT_CLIENT_OPTIONS ) options.update( DEFAULT_CLIENT_OPTIONS )

View File

@ -0,0 +1,54 @@
# coding: utf-8
#
# Copyright (C) 2016 YouCompleteMe contributors
#
# 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 ycm.tests.test_utils import ( CurrentWorkingDirectory, MockVimModule,
MockVimBuffers, VimBuffer )
MockVimModule()
from hamcrest import assert_that, empty, has_entries
from ycm.tests import PathToTestFile, YouCompleteMeInstance
@YouCompleteMeInstance()
def CreateCompletionRequest_UnicodeWorkingDirectory_test( ycm ):
unicode_dir = PathToTestFile( 'uni¢𐍈d€' )
current_buffer = VimBuffer( PathToTestFile( 'uni¢𐍈d€', 'current_buffer' ) )
with CurrentWorkingDirectory( unicode_dir ):
with MockVimBuffers( [ current_buffer ], current_buffer, ( 5, 2 ) ):
ycm.CreateCompletionRequest(),
results = ycm.GetCompletions()
assert_that(
results,
has_entries( {
'words': empty(),
'refresh': 'always'
} )
)

View File

@ -1,3 +1,5 @@
# coding: utf-8
#
# Copyright (C) 2015-2016 YouCompleteMe contributors # Copyright (C) 2015-2016 YouCompleteMe contributors
# #
# This file is part of YouCompleteMe. # This file is part of YouCompleteMe.
@ -23,17 +25,18 @@ from future import standard_library
standard_library.install_aliases() standard_library.install_aliases()
from builtins import * # noqa from builtins import * # noqa
from ycm.tests.test_utils import ExtendedMock, MockVimModule, VimBuffer from ycm.tests.test_utils import ( CurrentWorkingDirectory, ExtendedMock,
MockVimBuffers, MockVimModule, VimBuffer )
MockVimModule() MockVimModule()
import contextlib import contextlib
import os import os
from ycm.tests import YouCompleteMeInstance from ycm.tests import PathToTestFile, YouCompleteMeInstance
from ycmd.responses import ( BuildDiagnosticData, Diagnostic, Location, Range, from ycmd.responses import ( BuildDiagnosticData, Diagnostic, Location, Range,
UnknownExtraConf, ServerError ) UnknownExtraConf, ServerError )
from hamcrest import assert_that, contains, has_entries from hamcrest import assert_that, contains, has_entries, has_item
from mock import call, MagicMock, patch from mock import call, MagicMock, patch
from nose.tools import eq_, ok_ from nose.tools import eq_, ok_
@ -56,23 +59,17 @@ def UnplaceSign_Call( sign_id, buffer_num ):
@contextlib.contextmanager @contextlib.contextmanager
def MockArbitraryBuffer( filetype, native_available = True ): def MockArbitraryBuffer( filetype ):
"""Used via the with statement, set up mocked versions of the vim module such """Used via the with statement, set up a single buffer with an arbitrary name
that a single buffer is open with an arbitrary name and arbirary contents. Its and no contents. Its filetype is set to the supplied filetype."""
filetype is set to the supplied filetype"""
# Arbitrary, but valid, single buffer open. # Arbitrary, but valid, single buffer open.
current_buffer = VimBuffer( os.path.realpath( 'TEST_BUFFER' ), current_buffer = VimBuffer( os.path.realpath( 'TEST_BUFFER' ),
window = 1, window = 1,
filetype = filetype ) filetype = filetype )
# The rest just mock up the Vim module so that our single arbitrary buffer with MockVimBuffers( [ current_buffer ], current_buffer ):
# makes sense to vimsupport module. yield
with patch( 'vim.buffers', [ current_buffer ] ):
with patch( 'vim.current.buffer', current_buffer ):
# Arbitrary but valid cursor position.
with patch( 'vim.current.window.cursor', ( 1, 2 ) ):
yield
@contextlib.contextmanager @contextlib.contextmanager
@ -352,6 +349,44 @@ def _Check_FileReadyToParse_Diagnostic_Clean( ycm, vim_command ):
eq_( ycm.GetWarningCount(), 0 ) eq_( ycm.GetWarningCount(), 0 )
@patch( 'ycm.youcompleteme.YouCompleteMe._AddUltiSnipsDataIfNeeded' )
@YouCompleteMeInstance( { 'collect_identifiers_from_tags_files': 1 } )
def EventNotification_FileReadyToParse_TagFiles_UnicodeWorkingDirectory_test(
ycm, *args ):
unicode_dir = PathToTestFile( 'uni¢𐍈d€' )
current_buffer_file = PathToTestFile( 'uni¢𐍈d€', 'current_buffer' )
current_buffer = VimBuffer( name = current_buffer_file,
contents = [ 'current_buffer_contents' ],
filetype = 'some_filetype' )
with patch( 'ycm.client.base_request.BaseRequest.'
'PostDataToHandlerAsync' ) as post_data_to_handler_async:
with CurrentWorkingDirectory( unicode_dir ):
with MockVimBuffers( [ current_buffer ], current_buffer, ( 6, 5 ) ):
ycm.OnFileReadyToParse()
assert_that(
# Positional arguments passed to PostDataToHandlerAsync.
post_data_to_handler_async.call_args[ 0 ],
contains(
has_entries( {
'filepath': current_buffer_file,
'line_num': 6,
'column_num': 6,
'file_data': has_entries( {
current_buffer_file: has_entries( {
'contents': 'current_buffer_contents\n',
'filetypes': [ 'some_filetype' ]
} )
} ),
'event_name': 'FileReadyToParse',
'tag_files': has_item( PathToTestFile( 'uni¢𐍈d€', 'tags' ) )
} ),
'event_notification'
)
)
@patch( 'ycm.youcompleteme.YouCompleteMe._AddUltiSnipsDataIfNeeded' ) @patch( 'ycm.youcompleteme.YouCompleteMe._AddUltiSnipsDataIfNeeded' )
@YouCompleteMeInstance() @YouCompleteMeInstance()
def EventNotification_BufferVisit_BuildRequestForCurrentAndUnsavedBuffers_test( def EventNotification_BufferVisit_BuildRequestForCurrentAndUnsavedBuffers_test(
@ -380,12 +415,10 @@ def EventNotification_BufferVisit_BuildRequestForCurrentAndUnsavedBuffers_test(
with patch( 'ycm.client.base_request.BaseRequest.' with patch( 'ycm.client.base_request.BaseRequest.'
'PostDataToHandlerAsync' ) as post_data_to_handler_async: 'PostDataToHandlerAsync' ) as post_data_to_handler_async:
with patch( 'vim.buffers', [ current_buffer, with MockVimBuffers( [ current_buffer, modified_buffer, unmodified_buffer ],
modified_buffer, current_buffer,
unmodified_buffer ] ): ( 3, 5 ) ):
with patch( 'vim.current.buffer', current_buffer ): ycm.OnBufferVisit()
with patch( 'vim.current.window.cursor', ( 3, 5 ) ):
ycm.OnBufferVisit()
assert_that( assert_that(
# Positional arguments passed to PostDataToHandlerAsync. # Positional arguments passed to PostDataToHandlerAsync.
@ -431,9 +464,8 @@ def EventNotification_BufferUnload_BuildRequestForDeletedAndUnsavedBuffers_test(
with patch( 'ycm.client.base_request.BaseRequest.' with patch( 'ycm.client.base_request.BaseRequest.'
'PostDataToHandlerAsync' ) as post_data_to_handler_async: 'PostDataToHandlerAsync' ) as post_data_to_handler_async:
with patch( 'vim.buffers', [ current_buffer, deleted_buffer ] ): with MockVimBuffers( [ current_buffer, deleted_buffer ], current_buffer ):
with patch( 'vim.current.buffer', current_buffer ): ycm.OnBufferUnload( deleted_buffer_file )
ycm.OnBufferUnload( deleted_buffer_file )
assert_that( assert_that(
# Positional arguments passed to PostDataToHandlerAsync. # Positional arguments passed to PostDataToHandlerAsync.

View File

@ -24,12 +24,14 @@ from future import standard_library
standard_library.install_aliases() standard_library.install_aliases()
from builtins import * # noqa from builtins import * # noqa
from mock import MagicMock from mock import MagicMock, patch
from hamcrest import assert_that, equal_to from hamcrest import assert_that, equal_to
import contextlib
import functools
import nose
import os
import re import re
import sys import sys
import nose
import functools
from ycmd.utils import ToUnicode from ycmd.utils import ToUnicode
@ -52,21 +54,31 @@ GETBUFVAR_REGEX = re.compile(
VIM_MOCK = MagicMock() VIM_MOCK = MagicMock()
def MockGetBufferNumber( buffer_filename ): @contextlib.contextmanager
def CurrentWorkingDirectory( path ):
old_cwd = os.getcwd()
os.chdir( path )
try:
yield
finally:
os.chdir( old_cwd )
def _MockGetBufferNumber( buffer_filename ):
for vim_buffer in VIM_MOCK.buffers: for vim_buffer in VIM_MOCK.buffers:
if vim_buffer.name == buffer_filename: if vim_buffer.name == buffer_filename:
return vim_buffer.number return vim_buffer.number
return -1 return -1
def MockGetBufferWindowNumber( buffer_number ): def _MockGetBufferWindowNumber( buffer_number ):
for vim_buffer in VIM_MOCK.buffers: for vim_buffer in VIM_MOCK.buffers:
if vim_buffer.number == buffer_number and vim_buffer.window: if vim_buffer.number == buffer_number and vim_buffer.window:
return vim_buffer.window return vim_buffer.window
return -1 return -1
def MockGetBufferVariable( buffer_number, option ): def _MockGetBufferVariable( buffer_number, option ):
for vim_buffer in VIM_MOCK.buffers: for vim_buffer in VIM_MOCK.buffers:
if vim_buffer.number == buffer_number: if vim_buffer.number == buffer_number:
if option == 'mod': if option == 'mod':
@ -77,20 +89,7 @@ def MockGetBufferVariable( buffer_number, option ):
return '' return ''
def MockVimEval( value ): def _MockVimBufferEval( 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
if value == '&omnifunc': if value == '&omnifunc':
return VIM_MOCK.current.buffer.omnifunc return VIM_MOCK.current.buffer.omnifunc
@ -100,23 +99,66 @@ def MockVimEval( value ):
match = BUFNR_REGEX.search( value ) match = BUFNR_REGEX.search( value )
if match: if match:
buffer_filename = match.group( 'buffer_filename' ) buffer_filename = match.group( 'buffer_filename' )
return MockGetBufferNumber( buffer_filename ) return _MockGetBufferNumber( buffer_filename )
match = BUFWINNR_REGEX.search( value ) match = BUFWINNR_REGEX.search( value )
if match: if match:
buffer_number = int( match.group( 'buffer_number' ) ) buffer_number = int( match.group( 'buffer_number' ) )
return MockGetBufferWindowNumber( buffer_number ) return _MockGetBufferWindowNumber( buffer_number )
match = GETBUFVAR_REGEX.search( value ) match = GETBUFVAR_REGEX.search( value )
if match: if match:
buffer_number = int( match.group( 'buffer_number' ) ) buffer_number = int( match.group( 'buffer_number' ) )
option = match.group( 'option' ) option = match.group( 'option' )
return MockGetBufferVariable( buffer_number, option ) return _MockGetBufferVariable( buffer_number, option )
return None
def _MockVimOptionsEval( value ):
if value == '&previewheight':
return 12
if value == '&columns':
return 80
if value == '&ruler':
return 0
if value == '&showcmd':
return 1
return None
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 == 'complete_check()':
return 0
if value == 'tagfiles()':
return [ 'tags' ]
result = _MockVimOptionsEval( value )
if result is not None:
return result
result = _MockVimBufferEval( value )
if result is not None:
return result
raise ValueError( 'Unexpected evaluation: {0}'.format( value ) ) raise ValueError( 'Unexpected evaluation: {0}'.format( value ) )
def MockWipeoutBuffer( buffer_number ): def _MockWipeoutBuffer( buffer_number ):
buffers = VIM_MOCK.buffers buffers = VIM_MOCK.buffers
for index, buffer in enumerate( buffers ): for index, buffer in enumerate( buffers ):
@ -127,7 +169,7 @@ def MockWipeoutBuffer( buffer_number ):
def MockVimCommand( command ): def MockVimCommand( command ):
match = BWIPEOUT_REGEX.search( command ) match = BWIPEOUT_REGEX.search( command )
if match: if match:
return MockWipeoutBuffer( int( match.group( 1 ) ) ) return _MockWipeoutBuffer( int( match.group( 1 ) ) )
raise RuntimeError( 'Unexpected command: ' + command ) raise RuntimeError( 'Unexpected command: ' + command )
@ -159,7 +201,7 @@ class VimBuffer( object ):
def __getitem__( self, index ): def __getitem__( self, index ):
"""Return the bytes for a given line at index |index|.""" """Returns the bytes for a given line at index |index|."""
return self.contents[ index ] return self.contents[ index ]
@ -172,10 +214,24 @@ class VimBuffer( object ):
def GetLines( self ): def GetLines( self ):
"""Return the contents of the buffer as a list of unicode strings.""" """Returns the contents of the buffer as a list of unicode strings."""
return [ ToUnicode( x ) for x in self.contents ] return [ ToUnicode( x ) for x in self.contents ]
@contextlib.contextmanager
def MockVimBuffers( buffers, current_buffer, cursor_position = ( 1, 1 ) ):
"""Simulates the Vim buffers list |buffers| where |current_buffer| is the
buffer displayed in the current window and |cursor_position| is the current
cursor position. All buffers are represented by a VimBuffer object."""
if current_buffer not in buffers:
raise RuntimeError( 'Current buffer must be part of the buffers list.' )
with patch( 'vim.buffers', buffers ):
with patch( 'vim.current.buffer', current_buffer ):
with patch( 'vim.current.window.cursor', cursor_position ):
yield
def MockVimModule(): def MockVimModule():
"""The 'vim' module is something that is only present when running inside the """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 Vim Python interpreter, so we replace it with a MagicMock for tests. If you
@ -199,7 +255,7 @@ def MockVimModule():
tests.""" tests."""
VIM_MOCK.buffers = {} VIM_MOCK.buffers = {}
VIM_MOCK.eval = MagicMock( side_effect = MockVimEval ) VIM_MOCK.eval = MagicMock( side_effect = _MockVimEval )
sys.modules[ 'vim' ] = VIM_MOCK sys.modules[ 'vim' ] = VIM_MOCK
return VIM_MOCK return VIM_MOCK

View File

View File

@ -25,13 +25,14 @@ from future import standard_library
standard_library.install_aliases() standard_library.install_aliases()
from builtins import * # noqa from builtins import * # noqa
from ycm.tests.test_utils import ( ExtendedMock, MockVimCommand, VimBuffer, from ycm.tests import PathToTestFile
MockVimModule ) from ycm.tests.test_utils import ( CurrentWorkingDirectory, ExtendedMock,
MockVimCommand, MockVimModule, VimBuffer )
MockVimModule() MockVimModule()
from ycm import vimsupport from ycm import vimsupport
from nose.tools import eq_ from nose.tools import eq_
from hamcrest import assert_that, calling, raises, none, has_entry from hamcrest import assert_that, calling, equal_to, has_entry, none, raises
from mock import MagicMock, call, patch from mock import MagicMock, call, patch
from ycmd.utils import ToBytes from ycmd.utils import ToBytes
import os import os
@ -1418,6 +1419,14 @@ def GetUnsavedAndSpecifiedBufferData_EncodedUnicodeCharsInBuffers_test():
has_entry( u'contents', u'abc\nfДa\n' ) ) ) has_entry( u'contents', u'abc\nfДa\n' ) ) )
def GetBufferFilepath_NoBufferName_UnicodeWorkingDirectory_test():
vim_buffer = VimBuffer( '', number = 42 )
unicode_dir = PathToTestFile( u'uni¢𐍈d€' )
with CurrentWorkingDirectory( unicode_dir ):
assert_that( vimsupport.GetBufferFilepath( vim_buffer ),
equal_to( os.path.join( unicode_dir, '42' ) ) )
# NOTE: Vim returns byte offsets for columns, not actual character columns. This # NOTE: Vim returns byte offsets for columns, not actual character columns. This
# makes 'ДД' have 4 columns: column 0, column 2 and column 4. # makes 'ДД' have 4 columns: column 0, column 2 and column 4.
@patch( 'vim.current.line', ToBytes( 'ДДaa' ) ) @patch( 'vim.current.line', ToBytes( 'ДДaa' ) )