diff --git a/python/ycm/test_utils.py b/python/ycm/test_utils.py index f060466b..3eb8fc36 100644 --- a/python/ycm/test_utils.py +++ b/python/ycm/test_utils.py @@ -18,18 +18,23 @@ # along with YouCompleteMe. If not, see . from mock import MagicMock +import re import sys + +BUFNR_REGEX = re.compile( r"bufnr\('(.+)', ([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. +# 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() + 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 @@ -55,8 +60,24 @@ def MockVimModule(): def VimEval( value ): if value == "g:ycm_min_num_of_chars_for_completion": return 0 - return '' + if value == "g:ycm_path_to_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: + 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 ) sys.modules[ 'vim' ] = VIM_MOCK diff --git a/python/ycm/tests/vimsupport_test.py b/python/ycm/tests/vimsupport_test.py index 936101a0..7f50c9be 100644 --- a/python/ycm/tests/vimsupport_test.py +++ b/python/ycm/tests/vimsupport_test.py @@ -22,7 +22,9 @@ MockVimModule() from ycm import vimsupport from nose.tools import eq_ +from hamcrest import assert_that, calling, raises, none from mock import MagicMock, call, patch +import os 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.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 ) vimsupport.WriteToPreviewWindow( "test" ) @@ -615,9 +609,8 @@ def WriteToPreviewWindow_test( vim_current, vim_command, vim_eval ): ], any_order = True ) -@patch( 'vim.eval', side_effect=_Mock_tempname ) @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 ) vimsupport.WriteToPreviewWindow( "test\ntest2" ) @@ -625,10 +618,9 @@ def WriteToPreviewWindow_MultiLine_test( vim_current, vim_eval ): slice( None, None, None ), [ 'test', 'test2' ] ) -@patch( 'vim.eval', side_effect=_Mock_tempname ) @patch( 'vim.command' ) @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 ) 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() -@patch( 'vim.eval', side_effect=_Mock_tempname ) @patch( 'vim.command' ) @patch( 'vim.current' ) -def WriteToPreviewWindow_JumpFail_MultiLine_test( vim_current, - vim_command, - vim_eval ): +def WriteToPreviewWindow_JumpFail_MultiLine_test( vim_current, vim_command ): 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.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 :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 ) + ] )