Add tests for Vim file and buffer operations

Refactor Vim mocking.
This commit is contained in:
micbou 2015-11-08 02:16:13 +01:00
parent 59b91817a0
commit f23cbae2a8
2 changed files with 103 additions and 21 deletions

View File

@ -18,18 +18,23 @@
# along with YouCompleteMe. If not, see <http://www.gnu.org/licenses/>. # along with YouCompleteMe. If not, see <http://www.gnu.org/licenses/>.
from mock import MagicMock from mock import MagicMock
import re
import sys import sys
BUFNR_REGEX = re.compile( r"bufnr\('(.+)', ([0-9]+)\)" )
# 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,
# and subsquent assignments to sys.modules[ 'vim' ] don't retrospectively update # and subsquent assignments to sys.modules[ 'vim' ] don't retrospectively
# them. The result is that while running the tests, we must assign only one # update them. The result is that while running the tests, we must assign only
# instance of MagicMock to sys.modules[ 'vim' ] and always return it. # one instance of MagicMock to sys.modules[ 'vim' ] and always return it.
# #
# More explanation is available: # More explanation is available:
# https://github.com/Valloric/YouCompleteMe/pull/1694 # https://github.com/Valloric/YouCompleteMe/pull/1694
VIM_MOCK = MagicMock() VIM_MOCK = MagicMock()
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
@ -55,8 +60,24 @@ def MockVimModule():
def VimEval( value ): def VimEval( value ):
if value == "g:ycm_min_num_of_chars_for_completion": if value == "g:ycm_min_num_of_chars_for_completion":
return 0 return 0
if value == "g:ycm_path_to_python_interpreter":
return '' return ''
if value == "tempname()":
return '_TEMP_FILE_'
if value == "&previewheight":
# Default value from Vim
return 12
match = BUFNR_REGEX.search( value )
if match:
filename = match.group( 1 )
buffers = VIM_MOCK.buffers
if filename in buffers and buffers[ filename ]:
return buffers[ filename ].pop( 0 )
return -1
raise ValueError( 'Unexpected evaluation: ' + value )
VIM_MOCK.buffers = {}
VIM_MOCK.eval = MagicMock( side_effect = VimEval ) VIM_MOCK.eval = MagicMock( side_effect = VimEval )
sys.modules[ 'vim' ] = VIM_MOCK sys.modules[ 'vim' ] = VIM_MOCK

View File

@ -22,7 +22,9 @@ 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
from mock import MagicMock, call, patch from mock import MagicMock, call, patch
import os
def ReplaceChunk_SingleLine_Repl_1_test(): def ReplaceChunk_SingleLine_Repl_1_test():
@ -582,17 +584,9 @@ def _BuildChunk( start_line, start_column, end_line, end_column,
} }
def _Mock_tempname( arg ):
if arg == 'tempname()':
return '_TEMP_FILE_'
raise ValueError( 'Unexpected evaluation: ' + arg )
@patch( 'vim.eval', side_effect=_Mock_tempname )
@patch( 'vim.command' ) @patch( 'vim.command' )
@patch( 'vim.current' ) @patch( 'vim.current' )
def WriteToPreviewWindow_test( vim_current, vim_command, vim_eval ): def WriteToPreviewWindow_test( vim_current, vim_command ):
vim_current.window.options.__getitem__ = MagicMock( return_value = True ) vim_current.window.options.__getitem__ = MagicMock( return_value = True )
vimsupport.WriteToPreviewWindow( "test" ) vimsupport.WriteToPreviewWindow( "test" )
@ -615,9 +609,8 @@ def WriteToPreviewWindow_test( vim_current, vim_command, vim_eval ):
], any_order = True ) ], any_order = True )
@patch( 'vim.eval', side_effect=_Mock_tempname )
@patch( 'vim.current' ) @patch( 'vim.current' )
def WriteToPreviewWindow_MultiLine_test( vim_current, vim_eval ): def WriteToPreviewWindow_MultiLine_test( vim_current ):
vim_current.window.options.__getitem__ = MagicMock( return_value = True ) vim_current.window.options.__getitem__ = MagicMock( return_value = True )
vimsupport.WriteToPreviewWindow( "test\ntest2" ) vimsupport.WriteToPreviewWindow( "test\ntest2" )
@ -625,10 +618,9 @@ def WriteToPreviewWindow_MultiLine_test( vim_current, vim_eval ):
slice( None, None, None ), [ 'test', 'test2' ] ) slice( None, None, None ), [ 'test', 'test2' ] )
@patch( 'vim.eval', side_effect=_Mock_tempname )
@patch( 'vim.command' ) @patch( 'vim.command' )
@patch( 'vim.current' ) @patch( 'vim.current' )
def WriteToPreviewWindow_JumpFail_test( vim_current, vim_command, vim_eval ): def WriteToPreviewWindow_JumpFail_test( vim_current, vim_command ):
vim_current.window.options.__getitem__ = MagicMock( return_value = False ) vim_current.window.options.__getitem__ = MagicMock( return_value = False )
vimsupport.WriteToPreviewWindow( "test" ) vimsupport.WriteToPreviewWindow( "test" )
@ -644,12 +636,9 @@ def WriteToPreviewWindow_JumpFail_test( vim_current, vim_command, vim_eval ):
vim_current.buffer.options.__setitem__.assert_not_called() vim_current.buffer.options.__setitem__.assert_not_called()
@patch( 'vim.eval', side_effect=_Mock_tempname )
@patch( 'vim.command' ) @patch( 'vim.command' )
@patch( 'vim.current' ) @patch( 'vim.current' )
def WriteToPreviewWindow_JumpFail_MultiLine_test( vim_current, def WriteToPreviewWindow_JumpFail_MultiLine_test( vim_current, vim_command ):
vim_command,
vim_eval ):
vim_current.window.options.__getitem__ = MagicMock( return_value = False ) vim_current.window.options.__getitem__ = MagicMock( return_value = False )
@ -665,3 +654,75 @@ def WriteToPreviewWindow_JumpFail_MultiLine_test( vim_current,
vim_current.buffer.__setitem__.assert_not_called() vim_current.buffer.__setitem__.assert_not_called()
vim_current.buffer.options.__setitem__.assert_not_called() vim_current.buffer.options.__setitem__.assert_not_called()
def CheckFilename_test():
assert_that(
calling( vimsupport.CheckFilename ).with_args( None ),
raises( RuntimeError, "'None' is not a valid filename" )
)
assert_that(
calling( vimsupport.CheckFilename ).with_args( 'nonexistent_file' ),
raises( RuntimeError,
"filename 'nonexistent_file' cannot be opened. "
"\[Errno 2\] No such file or directory: 'nonexistent_file'" )
)
assert_that( vimsupport.CheckFilename( __file__ ), none() )
def BufferExistsForFilename_test():
buffers = {
os.path.realpath( 'some_filename' ): [ 1 ],
}
with patch.dict( 'vim.buffers', buffers ):
eq_( vimsupport.BufferExistsForFilename( 'some_filename' ), True )
eq_( vimsupport.BufferExistsForFilename( 'another_filename' ), False )
@patch( 'vim.command' )
def CloseBuffersForFilename_test( vim_command ):
buffers = {
os.path.realpath( 'some_filename' ): [ 2, 5 ],
os.path.realpath( 'another_filename' ): [ 1 ]
}
with patch.dict( 'vim.buffers', buffers ):
vimsupport.CloseBuffersForFilename( 'some_filename' )
vim_command.assert_has_calls( [
call( 'silent! bwipeout! 2' ),
call( 'silent! bwipeout! 5' )
], any_order = True )
@patch( 'vim.command' )
@patch( 'vim.current' )
def OpenFilename_test( vim_current, vim_command ):
# Options used to open a logfile
options = {
'size': vimsupport.GetIntValue( '&previewheight' ),
'fix': True,
'watch': True,
'position': 'end'
}
vimsupport.OpenFilename( __file__, options )
vim_command.assert_has_calls( [
call( 'silent! 12split {0}'.format( __file__ ) ),
call( "exec "
"'au BufEnter <buffer> :silent! checktime {0}'".format( __file__ ) ),
call( 'silent! normal G zz' ),
call( 'silent! wincmd p' )
] )
vim_current.buffer.options.__setitem__.assert_has_calls( [
call( 'autoread', True ),
] )
vim_current.window.options.__setitem__.assert_has_calls( [
call( 'winfixheight', True )
] )