Rewrite omnifunc tests

The VimBuffer object now accepts a Python function as its omnifunc.
This commit is contained in:
micbou 2017-07-03 17:59:20 +02:00
parent 191b79ed65
commit db0b9ab335
No known key found for this signature in database
GPG Key ID: C7E8FD1F3BDA1E05
3 changed files with 540 additions and 588 deletions

View File

@ -361,7 +361,7 @@ def EventNotification_FileReadyToParse_TagFiles_UnicodeWorkingDirectory_test(
with patch( 'ycm.client.event_notification.EventNotification.' with patch( 'ycm.client.event_notification.EventNotification.'
'PostDataToHandlerAsync' ) as post_data_to_handler_async: 'PostDataToHandlerAsync' ) as post_data_to_handler_async:
with CurrentWorkingDirectory( unicode_dir ): with CurrentWorkingDirectory( unicode_dir ):
with MockVimBuffers( [ current_buffer ], current_buffer, ( 6, 5 ) ): with MockVimBuffers( [ current_buffer ], current_buffer, ( 1, 5 ) ):
ycm.OnFileReadyToParse() ycm.OnFileReadyToParse()
assert_that( assert_that(
@ -370,7 +370,7 @@ def EventNotification_FileReadyToParse_TagFiles_UnicodeWorkingDirectory_test(
contains( contains(
has_entries( { has_entries( {
'filepath': current_buffer_file, 'filepath': current_buffer_file,
'line_num': 6, 'line_num': 1,
'column_num': 6, 'column_num': 6,
'file_data': has_entries( { 'file_data': has_entries( {
current_buffer_file: has_entries( { current_buffer_file: has_entries( {
@ -416,7 +416,7 @@ def EventNotification_BufferVisit_BuildRequestForCurrentAndUnsavedBuffers_test(
'PostDataToHandlerAsync' ) as post_data_to_handler_async: 'PostDataToHandlerAsync' ) as post_data_to_handler_async:
with MockVimBuffers( [ current_buffer, modified_buffer, unmodified_buffer ], with MockVimBuffers( [ current_buffer, modified_buffer, unmodified_buffer ],
current_buffer, current_buffer,
( 3, 5 ) ): ( 1, 5 ) ):
ycm.OnBufferVisit() ycm.OnBufferVisit()
assert_that( assert_that(
@ -425,7 +425,7 @@ def EventNotification_BufferVisit_BuildRequestForCurrentAndUnsavedBuffers_test(
contains( contains(
has_entries( { has_entries( {
'filepath': current_buffer_file, 'filepath': current_buffer_file,
'line_num': 3, 'line_num': 1,
'column_num': 6, 'column_num': 6,
'file_data': has_entries( { 'file_data': has_entries( {
current_buffer_file: has_entries( { current_buffer_file: has_entries( {

File diff suppressed because it is too large Load Diff

View File

@ -23,6 +23,7 @@ from __future__ import absolute_import
# Not installing aliases from python-future; it's unreliable and slow. # Not installing aliases from python-future; it's unreliable and slow.
from builtins import * # noqa from builtins import * # noqa
from future.utils import PY2
from mock import MagicMock, patch from mock import MagicMock, patch
from hamcrest import assert_that, equal_to from hamcrest import assert_that, equal_to
import contextlib import contextlib
@ -32,7 +33,7 @@ import os
import re import re
import sys import sys
from ycmd.utils import GetCurrentDirectory, ToUnicode from ycmd.utils import GetCurrentDirectory, ToBytes, ToUnicode
BUFNR_REGEX = re.compile( '^bufnr\(\'(?P<buffer_filename>.+)\', ([01])\)$' ) BUFNR_REGEX = re.compile( '^bufnr\(\'(?P<buffer_filename>.+)\', ([01])\)$' )
@ -44,6 +45,8 @@ GETBUFVAR_REGEX = re.compile(
MATCHADD_REGEX = re.compile( MATCHADD_REGEX = re.compile(
'^matchadd\(\'(?P<group>.+)\', \'(?P<pattern>.+)\'\)$' ) '^matchadd\(\'(?P<group>.+)\', \'(?P<pattern>.+)\'\)$' )
MATCHDELETE_REGEX = re.compile( '^matchdelete\((?P<id>\d+)\)$' ) MATCHDELETE_REGEX = re.compile( '^matchdelete\((?P<id>\d+)\)$' )
OMNIFUNC_REGEX_FORMAT = (
'^{omnifunc_name}\((?P<findstart>[01]),[\'"](?P<base>.*)[\'"]\)$' )
# One-and only instance of mocked Vim object. The first 'import vim' that is # 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, # executed binds the vim module to the instance of MagicMock that is created,
@ -99,7 +102,7 @@ def _MockGetBufferVariable( buffer_number, option ):
def _MockVimBufferEval( value ): def _MockVimBufferEval( value ):
if value == '&omnifunc': if value == '&omnifunc':
return VIM_MOCK.current.buffer.omnifunc return VIM_MOCK.current.buffer.omnifunc_name
if value == '&filetype': if value == '&filetype':
return VIM_MOCK.current.buffer.filetype return VIM_MOCK.current.buffer.filetype
@ -120,6 +123,16 @@ def _MockVimBufferEval( value ):
option = match.group( 'option' ) option = match.group( 'option' )
return _MockGetBufferVariable( buffer_number, option ) return _MockGetBufferVariable( buffer_number, option )
current_buffer = VIM_MOCK.current.buffer
match = re.search( OMNIFUNC_REGEX_FORMAT.format(
omnifunc_name = current_buffer.omnifunc_name ),
value )
if match:
findstart = int( match.group( 'findstart' ) )
base = match.group( 'base' )
value = current_buffer.omnifunc( findstart, base )
return value if findstart else ToBytesOnPY2( value )
return None return None
@ -221,16 +234,24 @@ class VimBuffer( object ):
- |modified| : True if the buffer has unsaved changes, False otherwise; - |modified| : True if the buffer has unsaved changes, False otherwise;
- |bufhidden|: value of the 'bufhidden' option (see :h bufhidden); - |bufhidden|: value of the 'bufhidden' option (see :h bufhidden);
- |window| : number of the buffer window. None if the buffer is hidden; - |window| : number of the buffer window. None if the buffer is hidden;
- |omnifunc| : omni completion function used by the buffer.""" - |omnifunc| : omni completion function used by the buffer. Must be a Python
function that takes the same arguments and returns the same
values as a Vim completion function (:h complete-functions).
Example:
def Omnifunc( findstart, base ):
if findstart:
return 5
return [ 'a', 'b', 'c' ]"""
def __init__( self, name, def __init__( self, name,
number = 1, number = 1,
contents = [], contents = [ '' ],
filetype = '', filetype = '',
modified = False, modified = False,
bufhidden = '', bufhidden = '',
window = None, window = None,
omnifunc = '' ): omnifunc = None ):
self.name = os.path.realpath( name ) if name else '' self.name = os.path.realpath( name ) if name else ''
self.number = number self.number = number
self.contents = contents self.contents = contents
@ -239,6 +260,7 @@ class VimBuffer( object ):
self.bufhidden = bufhidden self.bufhidden = bufhidden
self.window = window self.window = window
self.omnifunc = omnifunc self.omnifunc = omnifunc
self.omnifunc_name = omnifunc.__name__ if omnifunc else ''
self.changedtick = 1 self.changedtick = 1
@ -292,9 +314,12 @@ def MockVimBuffers( buffers, current_buffer, cursor_position = ( 1, 1 ) ):
if current_buffer not in buffers: if current_buffer not in buffers:
raise RuntimeError( 'Current buffer must be part of the buffers list.' ) raise RuntimeError( 'Current buffer must be part of the buffers list.' )
line = current_buffer.contents[ cursor_position[ 0 ] - 1 ]
with patch( 'vim.buffers', buffers ): with patch( 'vim.buffers', buffers ):
with patch( 'vim.current.buffer', current_buffer ): with patch( 'vim.current.buffer', current_buffer ):
with patch( 'vim.current.window.cursor', cursor_position ): with patch( 'vim.current.window.cursor', cursor_position ):
with patch( 'vim.current.line', line ):
yield VIM_MOCK yield VIM_MOCK
@ -395,3 +420,20 @@ def ExpectedFailure( reason, *exception_matchers ):
return Wrapper return Wrapper
return decorator return decorator
def ToBytesOnPY2( data ):
# To test the omnifunc, etc. returning strings, which can be of different
# types depending on python version, we use ToBytes on PY2 and just the native
# str on python3. This roughly matches what happens between py2 and py3
# versions within Vim.
if not PY2:
return data
if isinstance( data, list ):
return [ ToBytesOnPY2( item ) for item in data ]
if isinstance( data, dict ):
for item in data:
data[ item ] = ToBytesOnPY2( data[ item ] )
return data
return ToBytes( data )