Пример #1
0
class YouCompleteMe_test():

    # Minimal options to create the YouCompleteMe object.
    DEFAULT_OPTIONS = {
        'ycm_server_log_level': 'info',
        'ycm_server_keep_logfiles': 0,
        'ycm_min_num_of_chars_for_completion': 2,
        'ycm_auto_trigger': 1,
        'ycm_semantic_triggers': {}
    }

    def setUp(self):
        with patch('vim.eval', side_effect=self.VimEval):
            user_options_store.SetAll(base.BuildServerConf())
            self.ycm = YouCompleteMe(user_options_store.GetAll())

    def tearDown(self):
        self.ycm.OnVimLeave()

    def VimEval(self, value):
        if value == 'g:':
            return self.DEFAULT_OPTIONS

    def YcmCoreNotImported_test(self):
        assert_that('ycm_core', is_not(is_in(sys.modules)))
Пример #2
0
 def Wrapper(*args, **kwargs):
     ycm = YouCompleteMe(_MakeUserOptions(custom_options))
     _WaitUntilReady()
     try:
         test(ycm, *args, **kwargs)
     finally:
         ycm.OnVimLeave()
         WaitUntilProcessIsTerminated(ycm._server_popen)
Пример #3
0
class YouCompleteMe_test():
    def setUp(self):
        self.ycm = YouCompleteMe(MagicMock(spec_set=dict))

    def tearDown(self):
        self.ycm.OnVimLeave()

    def YcmCoreNotImported_test(self):
        assert_that('ycm_core', is_not(is_in(sys.modules)))
class EventNotification_test(object):
    def setUp(self):
        options = dict(user_options_store.DefaultOptions())
        options.update(DEFAULT_CLIENT_OPTIONS)
        user_options_store.SetAll(options)

        self.server_state = YouCompleteMe(user_options_store.GetAll())
        pass

    def tearDown(self):
        if self.server_state:
            self.server_state.OnVimLeave()

    @patch('vim.command', new_callable=ExtendedMock)
    def FileReadyToParse_NonDiagnostic_Error_test(self, vim_command):
        # This test validates the behaviour of YouCompleteMe.HandleFileParseRequest
        # in combination with YouCompleteMe.OnFileReadyToParse when the completer
        # raises an exception handling FileReadyToParse event notification
        ERROR_TEXT = 'Some completer response text'

        def ErrorResponse(*args):
            raise RuntimeError(ERROR_TEXT)

        with MockArbitraryBuffer('javascript'):
            with MockEventNotification(ErrorResponse):
                self.server_state.OnFileReadyToParse()
                assert self.server_state.FileParseRequestReady()
                self.server_state.HandleFileParseRequest()

                # The first call raises a warning
                vim_command.assert_has_exact_calls([
                    PostVimMessage_Call(ERROR_TEXT),
                ])

                # Subsequent calls don't re-raise the warning
                self.server_state.HandleFileParseRequest()
                vim_command.assert_has_exact_calls([
                    PostVimMessage_Call(ERROR_TEXT),
                ])

                # But it does if a subsequent event raises again
                self.server_state.OnFileReadyToParse()
                assert self.server_state.FileParseRequestReady()
                self.server_state.HandleFileParseRequest()
                vim_command.assert_has_exact_calls([
                    PostVimMessage_Call(ERROR_TEXT),
                    PostVimMessage_Call(ERROR_TEXT),
                ])

    @patch('vim.command')
    def FileReadyToParse_NonDiagnostic_Error_NonNative_test(self, vim_command):
        with MockArbitraryBuffer('javascript'):
            with MockEventNotification(None, False):
                self.server_state.OnFileReadyToParse()
                self.server_state.HandleFileParseRequest()
                vim_command.assert_not_called()

    @patch('ycm.client.event_notification._LoadExtraConfFile',
           new_callable=ExtendedMock)
    @patch('ycm.client.event_notification._IgnoreExtraConfFile',
           new_callable=ExtendedMock)
    def FileReadyToParse_NonDiagnostic_ConfirmExtraConf_test(
            self, ignore_extra_conf, load_extra_conf, *args):

        # This test validates the behaviour of YouCompleteMe.HandleFileParseRequest
        # in combination with YouCompleteMe.OnFileReadyToParse when the completer
        # raises the (special) UnknownExtraConf exception

        FILE_NAME = 'a_file'
        MESSAGE = ('Found ' + FILE_NAME + '. Load? \n\n(Question can be '
                   'turned off with options, see YCM docs)')

        def UnknownExtraConfResponse(*args):
            raise UnknownExtraConf(FILE_NAME)

        with MockArbitraryBuffer('javascript'):
            with MockEventNotification(UnknownExtraConfResponse):

                # When the user accepts the extra conf, we load it
                with patch('ycm.vimsupport.PresentDialog',
                           return_value=0,
                           new_callable=ExtendedMock) as present_dialog:
                    self.server_state.OnFileReadyToParse()
                    assert self.server_state.FileParseRequestReady()
                    self.server_state.HandleFileParseRequest()

                    present_dialog.assert_has_exact_calls([
                        PresentDialog_Confirm_Call(MESSAGE),
                    ])
                    load_extra_conf.assert_has_exact_calls([
                        call(FILE_NAME),
                    ])

                    # Subsequent calls don't re-raise the warning
                    self.server_state.HandleFileParseRequest()

                    present_dialog.assert_has_exact_calls(
                        [PresentDialog_Confirm_Call(MESSAGE)])
                    load_extra_conf.assert_has_exact_calls([
                        call(FILE_NAME),
                    ])

                    # But it does if a subsequent event raises again
                    self.server_state.OnFileReadyToParse()
                    assert self.server_state.FileParseRequestReady()
                    self.server_state.HandleFileParseRequest()

                    present_dialog.assert_has_exact_calls([
                        PresentDialog_Confirm_Call(MESSAGE),
                        PresentDialog_Confirm_Call(MESSAGE),
                    ])
                    load_extra_conf.assert_has_exact_calls([
                        call(FILE_NAME),
                        call(FILE_NAME),
                    ])

                # When the user rejects the extra conf, we reject it
                with patch('ycm.vimsupport.PresentDialog',
                           return_value=1,
                           new_callable=ExtendedMock) as present_dialog:
                    self.server_state.OnFileReadyToParse()
                    assert self.server_state.FileParseRequestReady()
                    self.server_state.HandleFileParseRequest()

                    present_dialog.assert_has_exact_calls([
                        PresentDialog_Confirm_Call(MESSAGE),
                    ])
                    ignore_extra_conf.assert_has_exact_calls([
                        call(FILE_NAME),
                    ])

                    # Subsequent calls don't re-raise the warning
                    self.server_state.HandleFileParseRequest()

                    present_dialog.assert_has_exact_calls(
                        [PresentDialog_Confirm_Call(MESSAGE)])
                    ignore_extra_conf.assert_has_exact_calls([
                        call(FILE_NAME),
                    ])

                    # But it does if a subsequent event raises again
                    self.server_state.OnFileReadyToParse()
                    assert self.server_state.FileParseRequestReady()
                    self.server_state.HandleFileParseRequest()

                    present_dialog.assert_has_exact_calls([
                        PresentDialog_Confirm_Call(MESSAGE),
                        PresentDialog_Confirm_Call(MESSAGE),
                    ])
                    ignore_extra_conf.assert_has_exact_calls([
                        call(FILE_NAME),
                        call(FILE_NAME),
                    ])

    def FileReadyToParse_Diagnostic_Error_Native_test(self):
        self._Check_FileReadyToParse_Diagnostic_Error()
        self._Check_FileReadyToParse_Diagnostic_Warning()
        self._Check_FileReadyToParse_Diagnostic_Clean()

    @patch('vim.command')
    def _Check_FileReadyToParse_Diagnostic_Error(self, vim_command):
        # Tests Vim sign placement and error/warning count python API
        # when one error is returned.
        def DiagnosticResponse(*args):
            start = Location(1, 2, 'TEST_BUFFER')
            end = Location(1, 4, 'TEST_BUFFER')
            extent = Range(start, end)
            diagnostic = Diagnostic([], start, extent, 'expected ;', 'ERROR')
            return [BuildDiagnosticData(diagnostic)]

        with MockArbitraryBuffer('cpp'):
            with MockEventNotification(DiagnosticResponse):
                self.server_state.OnFileReadyToParse()
                ok_(self.server_state.FileParseRequestReady())
                self.server_state.HandleFileParseRequest()
                vim_command.assert_has_calls([PlaceSign_Call(1, 1, 0, True)])
                eq_(self.server_state.GetErrorCount(), 1)
                eq_(self.server_state.GetWarningCount(), 0)

                # Consequent calls to HandleFileParseRequest shouldn't mess with
                # existing diagnostics, when there is no new parse request.
                vim_command.reset_mock()
                ok_(not self.server_state.FileParseRequestReady())
                self.server_state.HandleFileParseRequest()
                vim_command.assert_not_called()
                eq_(self.server_state.GetErrorCount(), 1)
                eq_(self.server_state.GetWarningCount(), 0)

    @patch('vim.command')
    def _Check_FileReadyToParse_Diagnostic_Warning(self, vim_command):
        # Tests Vim sign placement/unplacement and error/warning count python API
        # when one warning is returned.
        # Should be called after _Check_FileReadyToParse_Diagnostic_Error
        def DiagnosticResponse(*args):
            start = Location(2, 2, 'TEST_BUFFER')
            end = Location(2, 4, 'TEST_BUFFER')
            extent = Range(start, end)
            diagnostic = Diagnostic([], start, extent, 'cast', 'WARNING')
            return [BuildDiagnosticData(diagnostic)]

        with MockArbitraryBuffer('cpp'):
            with MockEventNotification(DiagnosticResponse):
                self.server_state.OnFileReadyToParse()
                ok_(self.server_state.FileParseRequestReady())
                self.server_state.HandleFileParseRequest()
                vim_command.assert_has_calls(
                    [PlaceSign_Call(2, 2, 0, False),
                     UnplaceSign_Call(1, 0)])
                eq_(self.server_state.GetErrorCount(), 0)
                eq_(self.server_state.GetWarningCount(), 1)

                # Consequent calls to HandleFileParseRequest shouldn't mess with
                # existing diagnostics, when there is no new parse request.
                vim_command.reset_mock()
                ok_(not self.server_state.FileParseRequestReady())
                self.server_state.HandleFileParseRequest()
                vim_command.assert_not_called()
                eq_(self.server_state.GetErrorCount(), 0)
                eq_(self.server_state.GetWarningCount(), 1)

    @patch('vim.command')
    def _Check_FileReadyToParse_Diagnostic_Clean(self, vim_command):
        # Tests Vim sign unplacement and error/warning count python API
        # when there are no errors/warnings left.
        # Should be called after _Check_FileReadyToParse_Diagnostic_Warning
        with MockArbitraryBuffer('cpp'):
            with MockEventNotification(MagicMock(return_value=[])):
                self.server_state.OnFileReadyToParse()
                self.server_state.HandleFileParseRequest()
                vim_command.assert_has_calls([UnplaceSign_Call(2, 0)])
                eq_(self.server_state.GetErrorCount(), 0)
                eq_(self.server_state.GetWarningCount(), 0)
Пример #5
0
class PostComplete_test():

  def setUp( self ):
    self.ycm = YouCompleteMe( MagicMock( spec_set = dict ) )


  def tearDown( self ):
    self.ycm.OnVimLeave()


  @contextlib.contextmanager
  def _SetupForCsharpCompletionDone( self, completions ):
    with patch( 'ycm.vimsupport.InsertNamespace' ):
      with patch( 'ycm.vimsupport.TextBeforeCursor',
                  return_value = '   Test' ):
        request = MagicMock()
        request.Done = MagicMock( return_value = True )
        request.RawResponse = MagicMock( return_value = completions )
        self.ycm._latest_completion_request = request
        yield


  @patch( 'ycm.vimsupport.CurrentFiletypes', return_value = [ "cs" ] )
  def GetCompleteDoneHooks_ResultOnCsharp_test( self, *args ):
    result = self.ycm.GetCompleteDoneHooks()
    eq_( 1, len( list( result ) ) )


  @patch( 'ycm.vimsupport.CurrentFiletypes', return_value = [ "txt" ] )
  def GetCompleteDoneHooks_EmptyOnOtherFiletype_test( self, *args ):
    result = self.ycm.GetCompleteDoneHooks()
    eq_( 0, len( list( result ) ) )


  @patch( 'ycm.vimsupport.CurrentFiletypes', return_value = [ "txt" ] )
  def OnCompleteDone_WithActionCallsIt_test( self, *args ):
    action = MagicMock()
    self.ycm._complete_done_hooks[ "txt" ] = action
    self.ycm.OnCompleteDone()

    ok_( action.called )


  @patch( 'ycm.vimsupport.CurrentFiletypes', return_value = [ "txt" ] )
  def OnCompleteDone_NoActionNoError_test( self, *args ):
    self.ycm.OnCompleteDone()


  @patch( 'ycm.vimsupport.VimVersionAtLeast', return_value = True )
  @patch( 'ycm.vimsupport.GetVariableValue',
          GetVariableValue_CompleteItemIs( 'Test' ) )
  def FilterToCompletedCompletions_NewVim_MatchIsReturned_test( self, *args ):
    completions = [ BuildCompletion( "Test" ) ]

    result = self.ycm._FilterToMatchingCompletions( completions, False )

    eq_( list( result ), completions )


  @patch( 'ycm.vimsupport.VimVersionAtLeast', return_value = True )
  @patch( 'ycm.vimsupport.GetVariableValue',
          GetVariableValue_CompleteItemIs( 'A' ) )
  def FilterToCompletedCompletions_NewVim_ShortTextDoesntRaise_test( self,
                                                                     *args ):
    completions = [ BuildCompletion( "AAA" ) ]

    self.ycm._FilterToMatchingCompletions( completions, False )


  @patch( 'ycm.vimsupport.VimVersionAtLeast', return_value = True )
  @patch( 'ycm.vimsupport.GetVariableValue',
          GetVariableValue_CompleteItemIs( 'Test' ) )
  def FilterToCompletedCompletions_NewVim_ExactMatchIsReturned_test( self,
                                                                     *args ):
    completions = [ BuildCompletion( "Test" ) ]

    result = self.ycm._FilterToMatchingCompletions( completions, False )

    eq_( list( result ), completions )


  @patch( 'ycm.vimsupport.VimVersionAtLeast', return_value = True )
  @patch( 'ycm.vimsupport.GetVariableValue',
          GetVariableValue_CompleteItemIs( '   Quote' ) )
  def FilterToCompletedCompletions_NewVim_NonMatchIsntReturned_test( self,
                                                                     *args ):
    completions = [ BuildCompletion( "A" ) ]

    result = self.ycm._FilterToMatchingCompletions( completions, False )

    assert_that( list( result ), empty() )


  @patch( 'ycm.vimsupport.VimVersionAtLeast', return_value = False )
  @patch( 'ycm.vimsupport.TextBeforeCursor', return_value = "   Test" )
  def FilterToCompletedCompletions_OldVim_MatchIsReturned_test( self, *args ):
    completions = [ BuildCompletion( "Test" ) ]

    result = self.ycm._FilterToMatchingCompletions( completions, False )

    eq_( list( result ), completions )


  @patch( 'ycm.vimsupport.VimVersionAtLeast', return_value = False )
  @patch( 'ycm.vimsupport.TextBeforeCursor', return_value = "X" )
  def FilterToCompletedCompletions_OldVim_ShortTextDoesntRaise_test( self,
                                                                     *args ):
    completions = [ BuildCompletion( "AAA" ) ]

    self.ycm._FilterToMatchingCompletions( completions, False )


  @patch( 'ycm.vimsupport.VimVersionAtLeast', return_value = False )
  @patch( 'ycm.vimsupport.TextBeforeCursor', return_value = "Test" )
  def FilterToCompletedCompletions_OldVim_ExactMatchIsReturned_test( self,
                                                                     *args ):
    completions = [ BuildCompletion( "Test" ) ]

    result = self.ycm._FilterToMatchingCompletions( completions, False )

    eq_( list( result ), completions )


  @patch( 'ycm.vimsupport.VimVersionAtLeast', return_value = False )
  @patch( 'ycm.vimsupport.TextBeforeCursor', return_value = "   Quote" )
  def FilterToCompletedCompletions_OldVim_NonMatchIsntReturned_test( self,
                                                                     *args ):
    completions = [ BuildCompletion( "A" ) ]

    result = self.ycm._FilterToMatchingCompletions( completions, False )

    assert_that( list( result ), empty() )


  @patch( 'ycm.vimsupport.VimVersionAtLeast', return_value = False )
  @patch( 'ycm.vimsupport.TextBeforeCursor', return_value = "   Te" )
  def HasCompletionsThatCouldBeCompletedWithMoreText_OldVim_MatchIsReturned_test( # noqa
    self, *args ):
    completions = [ BuildCompletion( "Test" ) ]

    result = self.ycm._HasCompletionsThatCouldBeCompletedWithMoreText(
                                                                completions )

    eq_( result, True )


  @patch( 'ycm.vimsupport.VimVersionAtLeast', return_value = False )
  @patch( 'ycm.vimsupport.TextBeforeCursor', return_value = "X" )
  def HasCompletionsThatCouldBeCompletedWithMoreText_OldVim_ShortTextDoesntRaise_test( # noqa
    self, *args ):
    completions = [ BuildCompletion( "AAA" ) ]

    self.ycm._HasCompletionsThatCouldBeCompletedWithMoreText( completions )


  @patch( 'ycm.vimsupport.VimVersionAtLeast', return_value = False )
  @patch( 'ycm.vimsupport.TextBeforeCursor', return_value = "Test" )
  def HasCompletionsThatCouldBeCompletedWithMoreText_OldVim_ExactMatchIsntReturned_test( # noqa
    self, *args ):
    completions = [ BuildCompletion( "Test" ) ]

    result = self.ycm._HasCompletionsThatCouldBeCompletedWithMoreText(
                                                                completions )

    eq_( result, False )


  @patch( 'ycm.vimsupport.VimVersionAtLeast', return_value = False )
  @patch( 'ycm.vimsupport.TextBeforeCursor', return_value = "   Quote" )
  def HasCompletionsThatCouldBeCompletedWithMoreText_OldVim_NonMatchIsntReturned_test( # noqa
    self, *args ):
    completions = [ BuildCompletion( "A" ) ]

    result = self.ycm._HasCompletionsThatCouldBeCompletedWithMoreText(
                                                                completions )

    eq_( result, False )


  @patch( 'ycm.vimsupport.VimVersionAtLeast', return_value = True )
  @patch( 'ycm.vimsupport.GetVariableValue',
          GetVariableValue_CompleteItemIs( "Te") )
  @patch( 'ycm.vimsupport.TextBeforeCursor', return_value = "   Quote" )
  def HasCompletionsThatCouldBeCompletedWithMoreText_NewVim_MatchIsReturned_test( # noqa
    self, *args ):
    completions = [ BuildCompletion( "Test" ) ]

    result = self.ycm._HasCompletionsThatCouldBeCompletedWithMoreText(
                                                                completions )

    eq_( result, True )


  @patch( 'ycm.vimsupport.VimVersionAtLeast', return_value = True )
  @patch( 'ycm.vimsupport.GetVariableValue',
          GetVariableValue_CompleteItemIs( "X") )
  @patch( 'ycm.vimsupport.TextBeforeCursor', return_value = "   Quote" )
  def HasCompletionsThatCouldBeCompletedWithMoreText_NewVim_ShortTextDoesntRaise_test( # noqa
    self, *args ):
    completions = [ BuildCompletion( "AAA" ) ]

    self.ycm._HasCompletionsThatCouldBeCompletedWithMoreText( completions )


  @patch( 'ycm.vimsupport.VimVersionAtLeast', return_value = True )
  @patch( 'ycm.vimsupport.GetVariableValue',
          GetVariableValue_CompleteItemIs( "Test" ) )
  @patch( 'ycm.vimsupport.TextBeforeCursor', return_value = '   Quote' )
  def HasCompletionsThatCouldBeCompletedWithMoreText_NewVim_ExactMatchIsntReturned_test( # noqa
    self, *args ):
    completions = [ BuildCompletion( "Test" ) ]

    result = self.ycm._HasCompletionsThatCouldBeCompletedWithMoreText(
                                                                completions )

    eq_( result, False )


  @patch( 'ycm.vimsupport.VimVersionAtLeast', return_value = True )
  @patch( 'ycm.vimsupport.GetVariableValue',
          GetVariableValue_CompleteItemIs( "   Quote" ) )
  @patch( 'ycm.vimsupport.TextBeforeCursor', return_value = '   Quote' )
  def HasCompletionsThatCouldBeCompletedWithMoreText_NewVim_NonMatchIsntReturned_test( # noqa
    self, *args ):
    completions = [ BuildCompletion( "A" ) ]

    result = self.ycm._HasCompletionsThatCouldBeCompletedWithMoreText(
                                                                completions )

    eq_( result, False )


  def GetRequiredNamespaceImport_ReturnNoneForNoExtraData_test( self ):
    eq_( None, self.ycm._GetRequiredNamespaceImport( {} ) )


  def GetRequiredNamespaceImport_ReturnNamespaceFromExtraData_test( self ):
    namespace = "A_NAMESPACE"

    eq_( namespace, self.ycm._GetRequiredNamespaceImport(
      BuildCompletion( namespace )
    ) )


  def GetCompletionsUserMayHaveCompleted_ReturnEmptyIfNotDone_test( self ):
    with self._SetupForCsharpCompletionDone( [] ):
      self.ycm._latest_completion_request.Done = MagicMock(
        return_value = False )

      eq_( [], self.ycm.GetCompletionsUserMayHaveCompleted() )


  def GetCompletionsUserMayHaveCompleted_ReturnEmptyIfPendingMatches_NewVim_test( # noqa
    self ):
    completions = [ BuildCompletion( None ) ]
    with self._SetupForCsharpCompletionDone( completions ):
      with patch( 'ycm.vimsupport.VimVersionAtLeast', return_value = True ):
        with patch( 'ycm.vimsupport.GetVariableValue',
                    GetVariableValue_CompleteItemIs( 'Te' ) ):
          eq_( [], self.ycm.GetCompletionsUserMayHaveCompleted() )


  def GetCompletionsUserMayHaveCompleted_ReturnEmptyIfPendingMatches_OldVim_test( # noqa
    self, *args ):
    completions = [ BuildCompletion( None ) ]
    with self._SetupForCsharpCompletionDone( completions ):
      with patch( 'ycm.vimsupport.VimVersionAtLeast', return_value = True ):
        with patch( 'ycm.vimsupport.GetVariableValue',
                    GetVariableValue_CompleteItemIs( 'Te' ) ):
          eq_( [], self.ycm.GetCompletionsUserMayHaveCompleted() )


  def GetCompletionsUserMayHaveCompleted_ReturnMatchIfExactMatches_NewVim_test(
    self, *args ):
    info = [ "NS", "Test", "Abbr", "Menu", "Info", "Kind" ]
    completions = [ BuildCompletion( *info ) ]
    with self._SetupForCsharpCompletionDone( completions ):
      with patch( 'ycm.vimsupport.VimVersionAtLeast', return_value = True ):
        with patch( 'ycm.vimsupport.GetVariableValue',
                    GetVariableValue_CompleteItemIs( *info[ 1: ] ) ):
          eq_( completions, self.ycm.GetCompletionsUserMayHaveCompleted() )


  def GetCompletionsUserMayHaveCompleted_ReturnMatchIfExactMatchesEvenIfPartial_NewVim_test( # noqa
    self, *args ):
    info = [ "NS", "Test", "Abbr", "Menu", "Info", "Kind" ]
    completions = [ BuildCompletion( *info ),
                    BuildCompletion( insertion_text = "TestTest" ) ]
    with self._SetupForCsharpCompletionDone( completions ):
      with patch( 'ycm.vimsupport.VimVersionAtLeast', return_value = True ):
        with patch( 'ycm.vimsupport.GetVariableValue',
                    GetVariableValue_CompleteItemIs( *info[ 1: ] ) ):
          eq_( [ completions[ 0 ] ],
               self.ycm.GetCompletionsUserMayHaveCompleted() )


  def GetCompletionsUserMayHaveCompleted_DontReturnMatchIfNontExactMatchesAndPartial_NewVim_test( # noqa
    self ):
    info = [ "NS", "Test", "Abbr", "Menu", "Info", "Kind" ]
    completions = [ BuildCompletion( insertion_text = info[ 0 ] ),
                    BuildCompletion( insertion_text = "TestTest" ) ]
    with self._SetupForCsharpCompletionDone( completions ):
      with patch( 'ycm.vimsupport.VimVersionAtLeast', return_value = True ):
        with patch( 'ycm.vimsupport.GetVariableValue',
                    GetVariableValue_CompleteItemIs( *info[ 1: ] ) ):
          eq_( [], self.ycm.GetCompletionsUserMayHaveCompleted() )


  def GetCompletionsUserMayHaveCompleted_ReturnMatchIfMatches_NewVim_test(
    self, *args ):
    completions = [ BuildCompletion( None ) ]
    with self._SetupForCsharpCompletionDone( completions ):
      with patch( 'ycm.vimsupport.VimVersionAtLeast', return_value = True ):
        with patch( 'ycm.vimsupport.GetVariableValue',
                    GetVariableValue_CompleteItemIs( "Test" ) ):
          eq_( completions, self.ycm.GetCompletionsUserMayHaveCompleted() )


  def GetCompletionsUserMayHaveCompleted_ReturnMatchIfMatches_OldVim_test(
    self, *args ):
    completions = [ BuildCompletion( None ) ]
    with self._SetupForCsharpCompletionDone( completions ):
      with patch( 'ycm.vimsupport.VimVersionAtLeast', return_value = False ):
        eq_( completions, self.ycm.GetCompletionsUserMayHaveCompleted() )


  def PostCompleteCsharp_EmptyDoesntInsertNamespace_test( self, *args ):
    with self._SetupForCsharpCompletionDone( [] ):
      with patch( 'ycm.vimsupport.VimVersionAtLeast', return_value = False ):
        self.ycm._OnCompleteDone_Csharp()

      ok_( not vimsupport.InsertNamespace.called )


  def PostCompleteCsharp_ExistingWithoutNamespaceDoesntInsertNamespace_test(
    self, *args ):
    completions = [ BuildCompletion( None ) ]
    with self._SetupForCsharpCompletionDone( completions ):
      with patch( 'ycm.vimsupport.VimVersionAtLeast', return_value = False ):
        self.ycm._OnCompleteDone_Csharp()

      ok_( not vimsupport.InsertNamespace.called )


  def PostCompleteCsharp_ValueDoesInsertNamespace_test( self, *args ):
    namespace = "A_NAMESPACE"
    completions = [ BuildCompletion( namespace ) ]
    with self._SetupForCsharpCompletionDone( completions ):
      with patch( 'ycm.vimsupport.VimVersionAtLeast', return_value = False ):
        self.ycm._OnCompleteDone_Csharp()

        vimsupport.InsertNamespace.assert_called_once_with( namespace )

  def PostCompleteCsharp_InsertSecondNamespaceIfSelected_test( self, *args ):
    namespace = "A_NAMESPACE"
    namespace2 = "ANOTHER_NAMESPACE"
    completions = [
      BuildCompletion( namespace ),
      BuildCompletion( namespace2 ),
    ]
    with self._SetupForCsharpCompletionDone( completions ):
      with patch( 'ycm.vimsupport.VimVersionAtLeast', return_value = False ):
        with patch( 'ycm.vimsupport.PresentDialog', return_value = 1 ):
          self.ycm._OnCompleteDone_Csharp()

          vimsupport.InsertNamespace.assert_called_once_with( namespace2 )
class EventNotification_test(object):
    def setUp(self):
        options = dict(user_options_store.DefaultOptions())
        options.update(DEFAULT_CLIENT_OPTIONS)
        user_options_store.SetAll(options)

        self.server_state = YouCompleteMe(user_options_store.GetAll())
        pass

    def tearDown(self):
        if self.server_state:
            self.server_state.OnVimLeave()

    @patch('vim.command')
    def FileReadyToParse_NonDiagnostic_Error_test(self, vim_command):
        # This test validates the behaviour of YouCompleteMe.ValidateParseRequest in
        # combination with YouCompleteMe.OnFileReadyToParse when the completer
        # raises an exception handling FileReadyToParse event notification
        ERROR_TEXT = 'Some completer response text'

        def ErrorResponse(*args):
            raise RuntimeError(ERROR_TEXT)

        with MockArbitraryBuffer('javascript'):
            with MockEventNotification(ErrorResponse):
                self.server_state.OnFileReadyToParse()
                assert self.server_state.DiagnosticsForCurrentFileReady()
                self.server_state.ValidateParseRequest()

                # The first call raises a warning
                vim_command.assert_has_calls([
                    PostVimMessage_Call(ERROR_TEXT),
                ])

                # Subsequent calls don't re-raise the warning
                self.server_state.ValidateParseRequest()
                vim_command.assert_has_calls([
                    PostVimMessage_Call(ERROR_TEXT),
                ])

                # But it does if a subsequent event raises again
                self.server_state.OnFileReadyToParse()
                assert self.server_state.DiagnosticsForCurrentFileReady()
                self.server_state.ValidateParseRequest()
                vim_command.assert_has_calls([
                    PostVimMessage_Call(ERROR_TEXT),
                    PostVimMessage_Call(ERROR_TEXT),
                ])

    @patch('vim.command')
    def FileReadyToParse_NonDiagnostic_Error_NonNative_test(self, vim_command):
        with MockArbitraryBuffer('javascript'):
            with MockEventNotification(None, False):
                self.server_state.OnFileReadyToParse()
                self.server_state.ValidateParseRequest()
                vim_command.assert_not_called()

    @patch('ycm.client.event_notification._LoadExtraConfFile')
    @patch('ycm.client.event_notification._IgnoreExtraConfFile')
    def FileReadyToParse_NonDiagnostic_ConfirmExtraConf_test(
            self, ignore_extra_conf, load_extra_conf, *args):

        # This test validates the behaviour of YouCompleteMe.ValidateParseRequest in
        # combination with YouCompleteMe.OnFileReadyToParse when the completer
        # raises the (special) UnknownExtraConf exception

        FILE_NAME = 'a_file'
        MESSAGE = ('Found ' + FILE_NAME + '. Load? \n\n(Question can be '
                   'turned off with options, see YCM docs)')

        def UnknownExtraConfResponse(*args):
            raise UnknownExtraConf(FILE_NAME)

        with MockArbitraryBuffer('javascript'):
            with MockEventNotification(UnknownExtraConfResponse):

                # When the user accepts the extra conf, we load it
                with patch('ycm.vimsupport.PresentDialog',
                           return_value=0) as present_dialog:
                    self.server_state.OnFileReadyToParse()
                    assert self.server_state.DiagnosticsForCurrentFileReady()
                    self.server_state.ValidateParseRequest()

                    present_dialog.assert_has_calls([
                        PresentDialog_Confirm_Call(MESSAGE),
                    ])
                    load_extra_conf.assert_has_calls([
                        call(FILE_NAME),
                    ])

                    # Subsequent calls don't re-raise the warning
                    self.server_state.ValidateParseRequest()

                    present_dialog.assert_has_calls(
                        [PresentDialog_Confirm_Call(MESSAGE)])
                    load_extra_conf.assert_has_calls([
                        call(FILE_NAME),
                    ])

                    # But it does if a subsequent event raises again
                    self.server_state.OnFileReadyToParse()
                    assert self.server_state.DiagnosticsForCurrentFileReady()
                    self.server_state.ValidateParseRequest()

                    present_dialog.assert_has_calls([
                        PresentDialog_Confirm_Call(MESSAGE),
                        PresentDialog_Confirm_Call(MESSAGE),
                    ])
                    load_extra_conf.assert_has_calls([
                        call(FILE_NAME),
                        call(FILE_NAME),
                    ])

                # When the user rejects the extra conf, we reject it
                with patch('ycm.vimsupport.PresentDialog',
                           return_value=1) as present_dialog:
                    self.server_state.OnFileReadyToParse()
                    assert self.server_state.DiagnosticsForCurrentFileReady()
                    self.server_state.ValidateParseRequest()

                    present_dialog.assert_has_calls([
                        PresentDialog_Confirm_Call(MESSAGE),
                    ])
                    ignore_extra_conf.assert_has_calls([
                        call(FILE_NAME),
                    ])

                    # Subsequent calls don't re-raise the warning
                    self.server_state.ValidateParseRequest()

                    present_dialog.assert_has_calls(
                        [PresentDialog_Confirm_Call(MESSAGE)])
                    ignore_extra_conf.assert_has_calls([
                        call(FILE_NAME),
                    ])

                    # But it does if a subsequent event raises again
                    self.server_state.OnFileReadyToParse()
                    assert self.server_state.DiagnosticsForCurrentFileReady()
                    self.server_state.ValidateParseRequest()

                    present_dialog.assert_has_calls([
                        PresentDialog_Confirm_Call(MESSAGE),
                        PresentDialog_Confirm_Call(MESSAGE),
                    ])
                    ignore_extra_conf.assert_has_calls([
                        call(FILE_NAME),
                        call(FILE_NAME),
                    ])
Пример #7
0
class OmniCompleter_test(object):
    def setUp(self):
        # We need a server instance for FilterAndSortCandidates
        self._server_state = YouCompleteMe(MakeUserOptions())

    def tearDown(self):
        self._server_state.OnVimLeave()

    def OmniCompleter_GetCompletions_Cache_List_test(self):
        omni_completer = OmniCompleter(MakeUserOptions({'cache_omnifunc': 1}))

        contents = 'test.'
        request_data = BuildRequestWrap(line_num=1,
                                        column_num=6,
                                        contents=contents)

        # Make sure there is an omnifunc set up.
        with patch('vim.eval', return_value=ToBytesOnPY2('test_omnifunc')):
            omni_completer.OnFileReadyToParse(request_data)

        omnifunc_result = [
            ToBytesOnPY2('a'),
            ToBytesOnPY2('b'),
            ToBytesOnPY2('cdef')
        ]

        # And get the completions
        with patch('vim.eval',
                   new_callable=ExtendedMock,
                   side_effect=[6, omnifunc_result]) as vim_eval:

            results = omni_completer.ComputeCandidates(request_data)
            vim_eval.assert_has_exact_calls([
                call('test_omnifunc(1,"")'),
                call("test_omnifunc(0,'')"),
            ])

            eq_(results, omnifunc_result)

    def OmniCompleter_GetCompletions_Cache_ListFilter_test(self):
        omni_completer = OmniCompleter(MakeUserOptions({'cache_omnifunc': 1}))

        contents = 'test.t'
        request_data = BuildRequestWrap(line_num=1,
                                        column_num=7,
                                        contents=contents)

        eq_(request_data['query'], 't')

        # Make sure there is an omnifunc set up.
        with patch('vim.eval', return_value=ToBytesOnPY2('test_omnifunc')):
            omni_completer.OnFileReadyToParse(request_data)

        omnifunc_result = [
            ToBytesOnPY2('a'),
            ToBytesOnPY2('b'),
            ToBytesOnPY2('cdef')
        ]

        # And get the completions
        with patch('vim.eval',
                   new_callable=ExtendedMock,
                   side_effect=[6, omnifunc_result]) as vim_eval:

            results = omni_completer.ComputeCandidates(request_data)
            vim_eval.assert_has_exact_calls([
                call('test_omnifunc(1,"")'),
                call("test_omnifunc(0,'t')"),
            ])

            eq_(results, [])

    def OmniCompleter_GetCompletions_NoCache_List_test(self):
        omni_completer = OmniCompleter(MakeUserOptions({'cache_omnifunc': 0}))

        contents = 'test.'
        request_data = BuildRequestWrap(line_num=1,
                                        column_num=6,
                                        contents=contents)

        # Make sure there is an omnifunc set up.
        with patch('vim.eval', return_value=ToBytesOnPY2('test_omnifunc')):
            omni_completer.OnFileReadyToParse(request_data)

        omnifunc_result = [
            ToBytesOnPY2('a'),
            ToBytesOnPY2('b'),
            ToBytesOnPY2('cdef')
        ]

        # And get the completions
        with patch('vim.eval',
                   new_callable=ExtendedMock,
                   side_effect=[6, omnifunc_result]) as vim_eval:

            results = omni_completer.ComputeCandidates(request_data)
            vim_eval.assert_has_exact_calls([
                call('test_omnifunc(1,"")'),
                call("test_omnifunc(0,'')"),
            ])

            eq_(results, omnifunc_result)

    def OmniCompleter_GetCompletions_NoCache_ListFilter_test(self):
        omni_completer = OmniCompleter(MakeUserOptions({'cache_omnifunc': 0}))

        contents = 'test.t'
        request_data = BuildRequestWrap(line_num=1,
                                        column_num=7,
                                        contents=contents)

        eq_(request_data['query'], 't')

        # Make sure there is an omnifunc set up.
        with patch('vim.eval', return_value=ToBytesOnPY2('test_omnifunc')):
            omni_completer.OnFileReadyToParse(request_data)

        omnifunc_result = [
            ToBytesOnPY2('a'),
            ToBytesOnPY2('b'),
            ToBytesOnPY2('cdef')
        ]

        # And get the completions
        with patch('vim.eval',
                   new_callable=ExtendedMock,
                   side_effect=[6, omnifunc_result]) as vim_eval:

            results = omni_completer.ComputeCandidates(request_data)
            vim_eval.assert_has_exact_calls([
                call('test_omnifunc(1,"")'),
                call("test_omnifunc(0,'t')"),
            ])

            # actual result is that the results are not filtered, as we expect the
            # omniufunc or vim itself to do this filtering
            eq_(results, omnifunc_result)

    @ExpectedFailure(
        'We ignore the result of the call to findstart and use our '
        'own interpretation of where the identifier should be',
        contains_string("test_omnifunc(0,'t')"))
    def OmniCompleter_GetCompletsions_UseFindStart_test(self):
        omni_completer = OmniCompleter(MakeUserOptions({'cache_omnifunc': 1}))

        contents = 'test.t'
        request_data = BuildRequestWrap(line_num=1,
                                        column_num=7,
                                        contents=contents)

        eq_(request_data['query'], 't')

        # Make sure there is an omnifunc set up.
        with patch('vim.eval', return_value=ToBytesOnPY2('test_omnifunc')):
            omni_completer.OnFileReadyToParse(request_data)

        omnifunc_result = [
            ToBytesOnPY2('a'),
            ToBytesOnPY2('b'),
            ToBytesOnPY2('cdef')
        ]

        # And get the completions
        with patch('vim.eval',
                   new_callable=ExtendedMock,
                   side_effect=[1, omnifunc_result]) as vim_eval:
            results = omni_completer.ComputeCandidates(request_data)

            vim_eval.assert_has_exact_calls([
                call('test_omnifunc(1,"")'),

                # Fails here: actual result is that the findstart result (1) is ignored
                # and we use the 't' query as we normally would on the server side
                call("test_omnifunc(0,'test.t')"),
            ])

            eq_(results, omnifunc_result)

    def OmniCompleter_GetCompletions_Cache_Object_test(self):
        omni_completer = OmniCompleter(MakeUserOptions({'cache_omnifunc': 1}))

        contents = 'test.t'
        request_data = BuildRequestWrap(line_num=1,
                                        column_num=7,
                                        contents=contents)

        eq_(request_data['query'], 't')

        # Make sure there is an omnifunc set up.
        with patch('vim.eval', return_value=ToBytesOnPY2('test_omnifunc')):
            omni_completer.OnFileReadyToParse(request_data)

        omnifunc_result = {
            'words':
            [ToBytesOnPY2('a'),
             ToBytesOnPY2('b'),
             ToBytesOnPY2('CDtEF')]
        }

        # And get the completions
        with patch('vim.eval',
                   new_callable=ExtendedMock,
                   side_effect=[6, omnifunc_result]) as vim_eval:

            results = omni_completer.ComputeCandidates(request_data)

            vim_eval.assert_has_exact_calls([
                call('test_omnifunc(1,"")'),
                call("test_omnifunc(0,'t')"),
            ])

            eq_(results, [ToBytesOnPY2('CDtEF')])

    def OmniCompleter_GetCompletions_Cache_ObjectList_test(self):
        omni_completer = OmniCompleter(MakeUserOptions({'cache_omnifunc': 1}))

        contents = 'test.tt'
        request_data = BuildRequestWrap(line_num=1,
                                        column_num=8,
                                        contents=contents)

        eq_(request_data['query'], 'tt')

        # Make sure there is an omnifunc set up.
        with patch('vim.eval', return_value=ToBytesOnPY2('test_omnifunc')):
            omni_completer.OnFileReadyToParse(request_data)

        omnifunc_result = [{
            'word': ToBytesOnPY2('a'),
            'abbr': ToBytesOnPY2('ABBR'),
            'menu': ToBytesOnPY2('MENU'),
            'info': ToBytesOnPY2('INFO'),
            'kind': ToBytesOnPY2('K')
        }, {
            'word': ToBytesOnPY2('test'),
            'abbr': ToBytesOnPY2('ABBRTEST'),
            'menu': ToBytesOnPY2('MENUTEST'),
            'info': ToBytesOnPY2('INFOTEST'),
            'kind': ToBytesOnPY2('T')
        }]

        # And get the completions
        with patch('vim.eval',
                   new_callable=ExtendedMock,
                   side_effect=[6, omnifunc_result]) as vim_eval:

            results = omni_completer.ComputeCandidates(request_data)

            vim_eval.assert_has_exact_calls([
                call('test_omnifunc(1,"")'),
                call("test_omnifunc(0,'tt')"),
            ])

            eq_(results, [omnifunc_result[1]])

    def OmniCompleter_GetCompletions_NoCache_ObjectList_test(self):
        omni_completer = OmniCompleter(MakeUserOptions({'cache_omnifunc': 0}))

        contents = 'test.tt'
        request_data = BuildRequestWrap(line_num=1,
                                        column_num=8,
                                        contents=contents)

        eq_(request_data['query'], 'tt')

        # Make sure there is an omnifunc set up.
        with patch('vim.eval', return_value=ToBytesOnPY2('test_omnifunc')):
            omni_completer.OnFileReadyToParse(request_data)

        omnifunc_result = [{
            'word': ToBytesOnPY2('a'),
            'abbr': ToBytesOnPY2('ABBR'),
            'menu': ToBytesOnPY2('MENU'),
            'info': ToBytesOnPY2('INFO'),
            'kind': ToBytesOnPY2('K')
        }, {
            'word': ToBytesOnPY2('test'),
            'abbr': ToBytesOnPY2('ABBRTEST'),
            'menu': ToBytesOnPY2('MENUTEST'),
            'info': ToBytesOnPY2('INFOTEST'),
            'kind': ToBytesOnPY2('T')
        }]

        # And get the completions
        with patch('vim.eval',
                   new_callable=ExtendedMock,
                   side_effect=[6, omnifunc_result]) as vim_eval:

            results = omni_completer.ComputeCandidates(request_data)

            vim_eval.assert_has_exact_calls([
                call('test_omnifunc(1,"")'),
                call("test_omnifunc(0,'tt')"),
            ])

            # We don't filter the result - we expect the omnifunc to do that
            # based on the query we supplied (Note: that means no fuzzy matching!)
            eq_(results, omnifunc_result)

    def OmniCompleter_GetCompletions_Cache_ObjectListObject_test(self):
        omni_completer = OmniCompleter(MakeUserOptions({'cache_omnifunc': 1}))

        contents = 'test.tt'
        request_data = BuildRequestWrap(line_num=1,
                                        column_num=8,
                                        contents=contents)

        eq_(request_data['query'], 'tt')

        # Make sure there is an omnifunc set up.
        with patch('vim.eval', return_value=ToBytesOnPY2('test_omnifunc')):
            omni_completer.OnFileReadyToParse(request_data)

        omnifunc_result = {
            'words': [{
                'word': ToBytesOnPY2('a'),
                'abbr': ToBytesOnPY2('ABBR'),
                'menu': ToBytesOnPY2('MENU'),
                'info': ToBytesOnPY2('INFO'),
                'kind': ToBytesOnPY2('K')
            }, {
                'word': ToBytesOnPY2('test'),
                'abbr': ToBytesOnPY2('ABBRTEST'),
                'menu': ToBytesOnPY2('MENUTEST'),
                'info': ToBytesOnPY2('INFOTEST'),
                'kind': ToBytesOnPY2('T')
            }]
        }

        # And get the completions
        with patch('vim.eval',
                   new_callable=ExtendedMock,
                   side_effect=[6, omnifunc_result]) as vim_eval:

            results = omni_completer.ComputeCandidates(request_data)

            vim_eval.assert_has_exact_calls([
                call('test_omnifunc(1,"")'),
                call("test_omnifunc(0,'tt')"),
            ])

            eq_(results, [omnifunc_result['words'][1]])

    def OmniCompleter_GetCompletions_NoCache_ObjectListObject_test(self):
        omni_completer = OmniCompleter(MakeUserOptions({'cache_omnifunc': 0}))

        contents = 'test.tt'
        request_data = BuildRequestWrap(line_num=1,
                                        column_num=8,
                                        contents=contents)

        eq_(request_data['query'], 'tt')

        # Make sure there is an omnifunc set up.
        with patch('vim.eval', return_value=ToBytesOnPY2('test_omnifunc')):
            omni_completer.OnFileReadyToParse(request_data)

        omnifunc_result = {
            'words': [{
                'word': ToBytesOnPY2('a'),
                'abbr': ToBytesOnPY2('ABBR'),
                'menu': ToBytesOnPY2('MENU'),
                'info': ToBytesOnPY2('INFO'),
                'kind': ToBytesOnPY2('K')
            }, {
                'word': ToBytesOnPY2('test'),
                'abbr': ToBytesOnPY2('ABBRTEST'),
                'menu': ToBytesOnPY2('MENUTEST'),
                'info': ToBytesOnPY2('INFOTEST'),
                'kind': ToBytesOnPY2('T')
            }]
        }

        # And get the completions
        with patch('vim.eval',
                   new_callable=ExtendedMock,
                   side_effect=[6, omnifunc_result]) as vim_eval:

            results = omni_completer.ComputeCandidates(request_data)

            vim_eval.assert_has_exact_calls([
                call('test_omnifunc(1,"")'),
                call("test_omnifunc(0,'tt')"),
            ])

            # No FilterAndSortCandidates for cache_omnifunc=0 (we expect the omnifunc
            # to do the filtering?)
            eq_(results, omnifunc_result['words'])

    def OmniCompleter_GetCompletions_Cache_List_Unicode_test(self):
        omni_completer = OmniCompleter(MakeUserOptions({'cache_omnifunc': 1}))

        contents = '†åsty_π.'
        request_data = BuildRequestWrap(line_num=1,
                                        column_num=13,
                                        contents=contents)

        # Make sure there is an omnifunc set up.
        with patch('vim.eval', return_value=ToBytesOnPY2('test_omnifunc')):
            omni_completer.OnFileReadyToParse(request_data)

        omnifunc_result = [
            ToBytesOnPY2('†est'),
            ToBytesOnPY2('å_unicode_identifier'),
            ToBytesOnPY2('πππππππ yummy πie')
        ]

        # And get the completions
        with patch('vim.eval',
                   new_callable=ExtendedMock,
                   side_effect=[6, omnifunc_result]) as vim_eval:

            results = omni_completer.ComputeCandidates(request_data)
            vim_eval.assert_has_exact_calls([
                call('test_omnifunc(1,"")'),
                call("test_omnifunc(0,'')"),
            ])

            eq_(results, omnifunc_result)

    def OmniCompleter_GetCompletions_NoCache_List_Unicode_test(self):
        omni_completer = OmniCompleter(MakeUserOptions({'cache_omnifunc': 0}))

        contents = '†åsty_π.'
        request_data = BuildRequestWrap(line_num=1,
                                        column_num=13,
                                        contents=contents)

        # Make sure there is an omnifunc set up.
        with patch('vim.eval', return_value=ToBytesOnPY2('test_omnifunc')):
            omni_completer.OnFileReadyToParse(request_data)

        omnifunc_result = [
            ToBytesOnPY2('†est'),
            ToBytesOnPY2('å_unicode_identifier'),
            ToBytesOnPY2('πππππππ yummy πie')
        ]

        # And get the completions
        with patch('vim.eval',
                   new_callable=ExtendedMock,
                   side_effect=[6, omnifunc_result]) as vim_eval:

            results = omni_completer.ComputeCandidates(request_data)
            vim_eval.assert_has_exact_calls([
                call('test_omnifunc(1,"")'),
                call("test_omnifunc(0,'')"),
            ])

            eq_(results, omnifunc_result)

    @ExpectedFailure('Filtering on unicode is not supported by the server')
    def OmniCompleter_GetCompletions_Cache_List_Filter_Unicode_test(self):
        omni_completer = OmniCompleter(MakeUserOptions({'cache_omnifunc': 1}))

        contents = '†åsty_π.ππ'
        request_data = BuildRequestWrap(line_num=1,
                                        column_num=17,
                                        contents=contents)

        # Make sure there is an omnifunc set up.
        with patch('vim.eval', return_value=ToBytesOnPY2('test_omnifunc')):
            omni_completer.OnFileReadyToParse(request_data)

        omnifunc_result = [
            ToBytesOnPY2('†est'),
            ToBytesOnPY2('å_unicode_identifier'),
            ToBytesOnPY2('πππππππ yummy πie')
        ]

        # And get the completions
        with patch('vim.eval',
                   new_callable=ExtendedMock,
                   side_effect=[6, omnifunc_result]) as vim_eval:

            results = omni_completer.ComputeCandidates(request_data)
            vim_eval.assert_has_exact_calls([
                call('test_omnifunc(1,"")'),
                call("test_omnifunc(0,'ππ')"),
            ])

            # Fails here: Filtering on unicode is not supported
            eq_(results, [omnifunc_result[2]])

    def OmniCompleter_GetCompletions_NoCache_List_Filter_Unicode_test(self):
        omni_completer = OmniCompleter(MakeUserOptions({'cache_omnifunc': 0}))

        contents = '†åsty_π.ππ'
        request_data = BuildRequestWrap(line_num=1,
                                        column_num=17,
                                        contents=contents)

        # Make sure there is an omnifunc set up.
        with patch('vim.eval', return_value=ToBytesOnPY2('test_omnifunc')):
            omni_completer.OnFileReadyToParse(request_data)

        omnifunc_result = [ToBytesOnPY2('πππππππ yummy πie')]

        # And get the completions
        with patch('vim.eval',
                   new_callable=ExtendedMock,
                   side_effect=[6, omnifunc_result]) as vim_eval:

            results = omni_completer.ComputeCandidates(request_data)
            vim_eval.assert_has_exact_calls([
                call('test_omnifunc(1,"")'),
                call("test_omnifunc(0,'ππ')"),
            ])

            eq_(results, omnifunc_result)

    @ExpectedFailure('Filtering on unicode is not supported by the server')
    def OmniCompleter_GetCompletions_Cache_ObjectList_Unicode_test(self):
        omni_completer = OmniCompleter(MakeUserOptions({'cache_omnifunc': 1}))

        contents = '†åsty_π.ππ'
        request_data = BuildRequestWrap(line_num=1,
                                        column_num=17,
                                        contents=contents)

        eq_(request_data['query'], 'ππ')

        # Make sure there is an omnifunc set up.
        with patch('vim.eval', return_value=ToBytesOnPY2('test_omnifunc')):
            omni_completer.OnFileReadyToParse(request_data)

        omnifunc_result = [{
            'word': ToBytesOnPY2('ålpha∫et'),
            'abbr': ToBytesOnPY2('å∫∫®'),
            'menu': ToBytesOnPY2('µ´~¨á'),
            'info': ToBytesOnPY2('^~fo'),
            'kind': ToBytesOnPY2('˚')
        }, {
            'word': ToBytesOnPY2('π†´ß†π'),
            'abbr': ToBytesOnPY2('ÅııÂʉÍÊ'),
            'menu': ToBytesOnPY2('˜‰ˆËʉÍÊ'),
            'info': ToBytesOnPY2('ȈÏØʉÍÊ'),
            'kind': ToBytesOnPY2('Ê')
        }]

        # And get the completions
        with patch('vim.eval',
                   new_callable=ExtendedMock,
                   side_effect=[6, omnifunc_result]) as vim_eval:

            results = omni_completer.ComputeCandidates(request_data)

            vim_eval.assert_has_exact_calls([
                call('test_omnifunc(1,"")'),
                call("test_omnifunc(0,'ππ')"),
            ])

            # Fails here: Filtering on unicode is not supported
            eq_(results, [omnifunc_result[1]])

    def OmniCompleter_GetCompletions_Cache_ObjectListObject_Unicode_test(self):
        omni_completer = OmniCompleter(MakeUserOptions({'cache_omnifunc': 1}))

        contents = '†åsty_π.t'
        request_data = BuildRequestWrap(line_num=1,
                                        column_num=14,
                                        contents=contents)

        eq_(request_data['query'], 't')

        # Make sure there is an omnifunc set up.
        with patch('vim.eval', return_value=ToBytesOnPY2('test_omnifunc')):
            omni_completer.OnFileReadyToParse(request_data)

        omnifunc_result = {
            'words': [{
                'word': ToBytesOnPY2('ålpha∫et'),
                'abbr': ToBytesOnPY2('å∫∫®'),
                'menu': ToBytesOnPY2('µ´~¨á'),
                'info': ToBytesOnPY2('^~fo'),
                'kind': ToBytesOnPY2('˚')
            }, {
                'word': ToBytesOnPY2('π†´ß†π'),
                'abbr': ToBytesOnPY2('ÅııÂʉÍÊ'),
                'menu': ToBytesOnPY2('˜‰ˆËʉÍÊ'),
                'info': ToBytesOnPY2('ȈÏØʉÍÊ'),
                'kind': ToBytesOnPY2('Ê')
            }, {
                'word': ToBytesOnPY2('test'),
                'abbr': ToBytesOnPY2('ÅııÂʉÍÊ'),
                'menu': ToBytesOnPY2('˜‰ˆËʉÍÊ'),
                'info': ToBytesOnPY2('ȈÏØʉÍÊ'),
                'kind': ToBytesOnPY2('Ê')
            }]
        }

        # And get the completions
        with patch('vim.eval',
                   new_callable=ExtendedMock,
                   side_effect=[6, omnifunc_result]) as vim_eval:

            results = omni_completer.ComputeCandidates(request_data)

            vim_eval.assert_has_exact_calls([
                call('test_omnifunc(1,"")'),
                call("test_omnifunc(0,'t')"),
            ])

            # Note: the filtered results are all unicode objects (not bytes) because
            # they are passed through the FilterAndSortCandidates machinery
            # (via the server)
            eq_(results, [{
                'word': 'test',
                'abbr': 'ÅııÂʉÍÊ',
                'menu': '˜‰ˆËʉÍÊ',
                'info': 'ȈÏØʉÍÊ',
                'kind': 'Ê'
            }])