diff --git a/python/ycm/test_utils.py b/python/ycm/test_utils.py index 3eb8fc36..4f9da546 100644 --- a/python/ycm/test_utils.py +++ b/python/ycm/test_utils.py @@ -22,7 +22,9 @@ import re import sys -BUFNR_REGEX = re.compile( r"bufnr\('(.+)', ([0-9]+)\)" ) +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, @@ -35,6 +37,58 @@ BUFNR_REGEX = re.compile( r"bufnr\('(.+)', ([0-9]+)\)" ) VIM_MOCK = MagicMock() +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_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: + 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 @@ -57,28 +111,8 @@ def MockVimModule(): Failure to use this approach may lead to unexpected failures in other tests.""" - def VimEval( value ): - if value == "g:ycm_min_num_of_chars_for_completion": - return 0 - 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 ) + VIM_MOCK.eval = MagicMock( side_effect = MockVimEval ) sys.modules[ 'vim' ] = VIM_MOCK return VIM_MOCK diff --git a/python/ycm/tests/vimsupport_test.py b/python/ycm/tests/vimsupport_test.py index 7f50c9be..4bfc9bb3 100644 --- a/python/ycm/tests/vimsupport_test.py +++ b/python/ycm/tests/vimsupport_test.py @@ -17,7 +17,7 @@ # You should have received a copy of the GNU General Public License # along with YouCompleteMe. If not, see . -from ycm.test_utils import MockVimModule +from ycm.test_utils import MockVimModule, MockVimCommand MockVimModule() from ycm import vimsupport @@ -672,24 +672,43 @@ def CheckFilename_test(): assert_that( vimsupport.CheckFilename( __file__ ), none() ) -def BufferExistsForFilename_test(): - buffers = { - os.path.realpath( 'some_filename' ): [ 1 ], - } +def BufferIsVisibleForFilename_test(): + buffers = [ + { + 'number': 1, + 'filename': os.path.realpath( 'visible_filename' ), + 'window': 1 + }, + { + 'number': 2, + 'filename': os.path.realpath( 'hidden_filename' ), + } + ] - with patch.dict( 'vim.buffers', buffers ): - eq_( vimsupport.BufferExistsForFilename( 'some_filename' ), True ) - eq_( vimsupport.BufferExistsForFilename( 'another_filename' ), False ) + with patch( 'vim.buffers', buffers ): + eq_( vimsupport.BufferIsVisibleForFilename( 'visible_filename' ), True ) + eq_( vimsupport.BufferIsVisibleForFilename( 'hidden_filename' ), False ) + eq_( vimsupport.BufferIsVisibleForFilename( 'another_filename' ), False ) -@patch( 'vim.command' ) +@patch( 'vim.command', side_effect = MockVimCommand ) def CloseBuffersForFilename_test( vim_command ): - buffers = { - os.path.realpath( 'some_filename' ): [ 2, 5 ], - os.path.realpath( 'another_filename' ): [ 1 ] - } + buffers = [ + { + 'number': 2, + 'filename': os.path.realpath( 'some_filename' ), + }, + { + 'number': 5, + 'filename': os.path.realpath( 'some_filename' ), + }, + { + 'number': 1, + 'filename': os.path.realpath( 'another_filename' ) + } + ] - with patch.dict( 'vim.buffers', buffers ): + with patch( 'vim.buffers', buffers ): vimsupport.CloseBuffersForFilename( 'some_filename' ) vim_command.assert_has_calls( [