Bläddra i källkod

Add tests for current directory

micbou 8 år sedan
förälder
incheckning
3109c9d8a4

+ 6 - 0
python/ycm/tests/__init__.py

@@ -27,6 +27,7 @@ from ycm.tests.test_utils import MockVimModule
 MockVimModule()
 
 import functools
+import os
 import requests
 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 = {} ):
   options = dict( user_options_store.DefaultOptions() )
   options.update( DEFAULT_CLIENT_OPTIONS )

+ 54 - 0
python/ycm/tests/completion_test.py

@@ -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'
+    } )
+  )

+ 55 - 23
python/ycm/tests/event_notification_test.py

@@ -1,3 +1,5 @@
+# coding: utf-8
+#
 # Copyright (C) 2015-2016 YouCompleteMe contributors
 #
 # This file is part of YouCompleteMe.
@@ -23,17 +25,18 @@ from future import standard_library
 standard_library.install_aliases()
 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()
 
 import contextlib
 import os
 
-from ycm.tests import YouCompleteMeInstance
+from ycm.tests import PathToTestFile, YouCompleteMeInstance
 from ycmd.responses import ( BuildDiagnosticData, Diagnostic, Location, Range,
                              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 nose.tools import eq_, ok_
 
@@ -56,23 +59,17 @@ def UnplaceSign_Call( sign_id, buffer_num ):
 
 
 @contextlib.contextmanager
-def MockArbitraryBuffer( filetype, native_available = True ):
-  """Used via the with statement, set up mocked versions of the vim module such
-  that a single buffer is open with an arbitrary name and arbirary contents. Its
-  filetype is set to the supplied filetype"""
+def MockArbitraryBuffer( filetype ):
+  """Used via the with statement, set up a single buffer with an arbitrary name
+  and no contents. Its filetype is set to the supplied filetype."""
 
   # Arbitrary, but valid, single buffer open.
   current_buffer = VimBuffer( os.path.realpath( 'TEST_BUFFER' ),
                               window = 1,
                               filetype = filetype )
 
-  # The rest just mock up the Vim module so that our single arbitrary buffer
-  # makes sense to vimsupport module.
-  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
+  with MockVimBuffers( [ current_buffer ], current_buffer ):
+    yield
 
 
 @contextlib.contextmanager
@@ -352,6 +349,44 @@ def _Check_FileReadyToParse_Diagnostic_Clean( ycm, vim_command ):
       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' )
 @YouCompleteMeInstance()
 def EventNotification_BufferVisit_BuildRequestForCurrentAndUnsavedBuffers_test(
@@ -380,12 +415,10 @@ def EventNotification_BufferVisit_BuildRequestForCurrentAndUnsavedBuffers_test(
 
   with patch( 'ycm.client.base_request.BaseRequest.'
               'PostDataToHandlerAsync' ) as post_data_to_handler_async:
-    with patch( 'vim.buffers', [ current_buffer,
-                                 modified_buffer,
-                                 unmodified_buffer ] ):
-      with patch( 'vim.current.buffer', current_buffer ):
-        with patch( 'vim.current.window.cursor', ( 3, 5 ) ):
-          ycm.OnBufferVisit()
+    with MockVimBuffers( [ current_buffer, modified_buffer, unmodified_buffer ],
+                         current_buffer,
+                         ( 3, 5 ) ):
+      ycm.OnBufferVisit()
 
     assert_that(
       # Positional arguments passed to PostDataToHandlerAsync.
@@ -431,9 +464,8 @@ def EventNotification_BufferUnload_BuildRequestForDeletedAndUnsavedBuffers_test(
 
   with patch( 'ycm.client.base_request.BaseRequest.'
               'PostDataToHandlerAsync' ) as post_data_to_handler_async:
-    with patch( 'vim.buffers', [ current_buffer, deleted_buffer ] ):
-      with patch( 'vim.current.buffer', current_buffer ):
-        ycm.OnBufferUnload( deleted_buffer_file )
+    with MockVimBuffers( [ current_buffer, deleted_buffer ], current_buffer ):
+      ycm.OnBufferUnload( deleted_buffer_file )
 
   assert_that(
     # Positional arguments passed to PostDataToHandlerAsync.

+ 84 - 28
python/ycm/tests/test_utils.py

@@ -24,12 +24,14 @@ from future import standard_library
 standard_library.install_aliases()
 from builtins import *  # noqa
 
-from mock import MagicMock
+from mock import MagicMock, patch
 from hamcrest import assert_that, equal_to
+import contextlib
+import functools
+import nose
+import os
 import re
 import sys
-import nose
-import functools
 
 from ycmd.utils import ToUnicode
 
@@ -52,21 +54,31 @@ GETBUFVAR_REGEX = re.compile(
 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:
     if vim_buffer.name == buffer_filename:
       return vim_buffer.number
   return -1
 
 
-def MockGetBufferWindowNumber( buffer_number ):
+def _MockGetBufferWindowNumber( buffer_number ):
   for vim_buffer in VIM_MOCK.buffers:
     if vim_buffer.number == buffer_number and vim_buffer.window:
       return vim_buffer.window
   return -1
 
 
-def MockGetBufferVariable( buffer_number, option ):
+def _MockGetBufferVariable( buffer_number, option ):
   for vim_buffer in VIM_MOCK.buffers:
     if vim_buffer.number == buffer_number:
       if option == 'mod':
@@ -77,20 +89,7 @@ def MockGetBufferVariable( buffer_number, option ):
   return ''
 
 
-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 == '&previewheight':
-    # Default value from Vim
-    return 12
-
+def _MockVimBufferEval( value ):
   if value == '&omnifunc':
     return VIM_MOCK.current.buffer.omnifunc
 
@@ -100,23 +99,66 @@ def MockVimEval( value ):
   match = BUFNR_REGEX.search( value )
   if match:
     buffer_filename = match.group( 'buffer_filename' )
-    return MockGetBufferNumber( buffer_filename )
+    return _MockGetBufferNumber( buffer_filename )
 
   match = BUFWINNR_REGEX.search( value )
   if match:
     buffer_number = int( match.group( 'buffer_number' ) )
-    return MockGetBufferWindowNumber( buffer_number )
+    return _MockGetBufferWindowNumber( buffer_number )
 
   match = GETBUFVAR_REGEX.search( value )
   if match:
     buffer_number = int( match.group( 'buffer_number' ) )
     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 ) )
 
 
-def MockWipeoutBuffer( buffer_number ):
+def _MockWipeoutBuffer( buffer_number ):
   buffers = VIM_MOCK.buffers
 
   for index, buffer in enumerate( buffers ):
@@ -127,7 +169,7 @@ def MockWipeoutBuffer( buffer_number ):
 def MockVimCommand( command ):
   match = BWIPEOUT_REGEX.search( command )
   if match:
-    return MockWipeoutBuffer( int( match.group( 1 ) ) )
+    return _MockWipeoutBuffer( int( match.group( 1 ) ) )
 
   raise RuntimeError( 'Unexpected command: ' + command )
 
@@ -159,7 +201,7 @@ class VimBuffer( object ):
 
 
   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 ]
 
 
@@ -172,10 +214,24 @@ class VimBuffer( object ):
 
 
   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 ]
 
 
+@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():
   """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
@@ -199,7 +255,7 @@ def MockVimModule():
   tests."""
 
   VIM_MOCK.buffers = {}
-  VIM_MOCK.eval = MagicMock( side_effect = MockVimEval )
+  VIM_MOCK.eval = MagicMock( side_effect = _MockVimEval )
   sys.modules[ 'vim' ] = VIM_MOCK
 
   return VIM_MOCK

+ 0 - 0
python/ycm/tests/testdata/uni¢𐍈d€/tags


+ 12 - 3
python/ycm/tests/vimsupport_test.py

@@ -25,13 +25,14 @@ from future import standard_library
 standard_library.install_aliases()
 from builtins import *  # noqa
 
-from ycm.tests.test_utils import ( ExtendedMock, MockVimCommand, VimBuffer,
-                                   MockVimModule )
+from ycm.tests import PathToTestFile
+from ycm.tests.test_utils import ( CurrentWorkingDirectory, ExtendedMock,
+                                   MockVimCommand, MockVimModule, VimBuffer )
 MockVimModule()
 
 from ycm import vimsupport
 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 ycmd.utils import ToBytes
 import os
@@ -1418,6 +1419,14 @@ def GetUnsavedAndSpecifiedBufferData_EncodedUnicodeCharsInBuffers_test():
                             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
 # makes 'ДД' have 4 columns: column 0, column 2 and column 4.
 @patch( 'vim.current.line', ToBytes( 'ДДaa' ) )