def StartJavaCompleterServerWithFile( app, file_path ): app.post_json( '/event_notification', BuildRequest( event_name = 'FileReadyToParse', filepath = file_path, filetype = 'java' ) ) WaitUntilCompleterServerReady( app, 'java', SERVER_STARTUP_TIMEOUT )
def ServerManagement_WipeWorkspace_WithConfig( app ): StartJavaCompleterServerInDirectory( app, PathToTestFile( 'simple_eclipse_project', 'src' ) ) project = PathToTestFile( 'simple_eclipse_project' ) filepath = PathToTestFile( 'simple_eclipse_project', 'src', 'com', 'youcompleteme', 'Test.java' ) app.post_json( '/run_completer_command', BuildRequest( filepath = filepath, filetype = 'java', command_arguments = [ 'WipeWorkspace', '--with-config' ], ), ) WaitUntilCompleterServerReady( app, 'java' ) assert_that( app.post_json( '/debug_info', BuildRequest( filetype = 'java', filepath = filepath ) ).json, CompleterProjectDirectoryMatcher( project ) )
def GenericLSPCompleter_SignatureHelp_NotASigHelpProvider_test(app, *args): test_file = PathToTestFile('generic_server', 'foo', 'bar', 'baz', 'test_file') request = BuildRequest(filepath=test_file, filetype='foo', line_num=1, column_num=1, contents='', event_name='FileReadyToParse') app.post_json('/event_notification', request) WaitUntilCompleterServerReady(app, 'foo') request.pop('event_name') response = app.post_json('/signature_help', request).json assert_that( response, has_entries({ 'signature_help': has_entries({ 'activeSignature': 0, 'activeParameter': 0, 'signatures': empty() }), 'errors': empty() }))
def setUpModule(): global shared_app with patch('ycmd.completers.javascript.hook.' 'ShouldEnableTernCompleter', return_value=False): shared_app = SetUpApp() WaitUntilCompleterServerReady(shared_app, 'javascriptreact')
def DebugInfo_HandleNotificationInPollThread_Throw_test(app): filepath = PathToTestFile(DEFAULT_PROJECT_DIR, 'src', 'com', 'youcompleteme', 'Test.java') StartJavaCompleterServerInDirectory(app, filepath) # This mock will be called in the message pump thread, so syncronize the # result (thrown) using an Event thrown = threading.Event() def ThrowOnLogMessage(msg): thrown.set() raise RuntimeError("ThrowOnLogMessage") with patch.object(lsc.LanguageServerCompleter, 'HandleNotificationInPollThread', side_effect=ThrowOnLogMessage): app.post_json( '/run_completer_command', BuildRequest( filepath=filepath, filetype='java', command_arguments=['RestartServer'], ), ) # Ensure that we still process and handle messages even though a # message-pump-thread-handler raised an error. WaitUntilCompleterServerReady(app, 'java') # Prove that the exception was thrown. assert_that(thrown.is_set(), equal_to(True))
def ServerManagement_RestartServer_test( app ): StartClangd( app, PathToTestFile( 'basic.cpp' ) ) assert_that( GetDebugInfo( app ), CompleterProjectDirectoryMatcher( PathToTestFile() ) ) app.post_json( '/run_completer_command', BuildRequest( filepath = PathToTestFile( 'test-include', 'main.cpp' ), filetype = 'cpp', command_arguments = [ 'RestartServer' ], ), ) WaitUntilCompleterServerReady( app, 'cpp' ) assert_that( GetDebugInfo( app ), has_entry( 'completer', has_entries( { 'name': 'C-family', 'servers': contains( has_entries( { 'name': 'Clangd', 'is_running': True, 'extras': has_item( has_entries( { 'key': 'Project Directory', 'value': PathToTestFile( 'test-include' ), } ) ) } ) ) } ) ) )
def Subcommands_StopServer_Timeout_test( app ): filepath = PathToTestFile( 'testy', 'GotoTestCase.cs' ) contents = ReadFile( filepath ) event_data = BuildRequest( filepath = filepath, filetype = 'cs', contents = contents, event_name = 'FileReadyToParse' ) app.post_json( '/event_notification', event_data ) WaitUntilCompleterServerReady( app, 'cs' ) app.post_json( '/run_completer_command', BuildRequest( filetype = 'cs', filepath = filepath, command_arguments = [ 'StopServer' ] ) ) request_data = BuildRequest( filetype = 'cs', filepath = filepath ) assert_that( app.post_json( '/debug_info', request_data ).json, has_entry( 'completer', has_entry( 'servers', contains( has_entry( 'is_running', False ) ) ) ) )
def StopServer_KeepLogFiles(app, keeping_log_files): with UserOption('server_keep_logfiles', keeping_log_files): filepath = PathToTestFile('testy', 'GotoTestCase.cs') contents = ReadFile(filepath) event_data = BuildRequest(filepath=filepath, filetype='cs', contents=contents, event_name='FileReadyToParse') app.post_json('/event_notification', event_data) WaitUntilCompleterServerReady(app, 'cs') event_data = BuildRequest(filetype='cs', filepath=filepath) response = app.post_json('/debug_info', event_data).json logfiles = [] for server in response['completer']['servers']: logfiles.extend(server['logfiles']) try: for logfile in logfiles: ok_(os.path.exists(logfile), 'Logfile should exist at {0}'.format(logfile)) finally: StopCompleterServer(app, 'cs', filepath) if keeping_log_files: for logfile in logfiles: ok_(os.path.exists(logfile), 'Logfile should still exist at {0}'.format(logfile)) else: for logfile in logfiles: ok_(not os.path.exists(logfile), 'Logfile should no longer exist at {0}'.format(logfile))
def StartJavaCompleterServerInDirectory( app, directory ): app.post_json( '/event_notification', BuildRequest( filepath = os.path.join( directory, 'test.java' ), event_name = 'FileReadyToParse', filetype = 'java' ) ) WaitUntilCompleterServerReady( shared_app, 'java', SERVER_STARTUP_TIMEOUT )
def GenericLSPCompleter_Diagnostics_test(app): request = BuildRequest(filepath=TEST_FILE, filetype='foo', line_num=1, column_num=1, contents=TEST_FILE_CONTENT, event_name='FileReadyToParse') app.post_json('/event_notification', request) WaitUntilCompleterServerReady(app, 'foo') request.pop('event_name') response = app.post_json('/receive_messages', request) assert_that( response.json, has_items( has_entries({ 'diagnostics': has_items( has_entries({ 'kind': equal_to('WARNING'), 'location': LocationMatcher(TEST_FILE, 2, 1), 'location_extent': RangeMatcher(TEST_FILE, (2, 1), (2, 4)), 'text': equal_to('FOO is all uppercase.'), 'fixit_available': False })) })))
def RunTest(app, test): """ Method to run a simple completion test and verify the result Note: Compile commands are extracted from a compile_flags.txt file by clangd by iteratively looking at the directory containing the source file and its ancestors. test is a dictionary containing: 'request': kwargs for BuildRequest 'expect': { 'response': server response code (e.g. requests.codes.ok) 'data': matcher for the server response json } """ request = test['request'] filetype = request.get('filetype', 'cpp') if 'contents' not in request: contents = ReadFile(request['filepath']) request['contents'] = contents request['filetype'] = filetype # Because we aren't testing this command, we *always* ignore errors. This # is mainly because we (may) want to test scenarios where the completer # throws an exception and the easiest way to do that is to throw from # within the Settings function. app.post_json('/event_notification', CombineRequest(request, { 'event_name': 'FileReadyToParse', 'filetype': filetype }), expect_errors=True) WaitUntilCompleterServerReady(app, filetype) for i in range(10): try: # We also ignore errors here, but then we check the response code ourself. # This is to allow testing of requests returning errors. response = app.post_json('/completions', BuildRequest(**request), expect_errors=True) assert_that(response.status_code, equal_to(test['expect']['response'])) print('Completer response: {}'.format( json.dumps(response.json, indent=2))) assert_that(response.json, test['expect']['data']) break except Exception: if i == 9: raise else: completer = handlers._server_state.GetFiletypeCompleter( ['cpp']) completer._completions_cache.Invalidate() sleep(0.1) pass
def GetCompletions_ChangeStartColumn_test(app): WaitUntilCompleterServerReady(app, 'javascript') RunTest( app, { 'description': 'the completion_start_column is updated by tern', 'request': { 'filetype': 'javascript', 'filepath': PathToTestFile('node', 'node_test.js'), 'line_num': 1, 'column_num': 17, 'force_semantic': True, }, 'expect': { 'response': requests.codes.ok, 'data': has_entries({ 'completions': contains(CompletionEntryMatcher('"path"', 'path')), 'completion_start_column': 14, 'errors': empty(), }) }, })
def StartJavaScriptCompleterServerInDirectory(app, directory): app.post_json( '/event_notification', BuildRequest(filepath=os.path.join(directory, 'test.js'), event_name='FileReadyToParse', filetype='javascript')) WaitUntilCompleterServerReady(app, 'javascript')
def Subcommands_FixIt_AlreadyResolved_test( app ): filename = PathToTestFile( 'FixIt_Clang_cpp11.cpp' ) request = { 'completer_target' : 'filetype_default', 'contents' : ReadFile( filename ), 'filepath' : filename, 'command_arguments': [ 'FixIt' ], 'line_num' : 16, 'column_num' : 1, 'filetype' : 'cpp' } app.post_json( '/event_notification', CombineRequest( request, { 'event_name': 'FileReadyToParse', } ), expect_errors = True ) WaitUntilCompleterServerReady( app, 'cpp' ) expected = app.post_json( '/run_completer_command', BuildRequest( **request ) ).json print( 'expected = ' ) print( expected ) request[ 'fixit' ] = expected[ 'fixits' ][ 0 ] actual = app.post_json( '/resolve_fixit', BuildRequest( **request ) ).json print( 'actual = ' ) print( actual ) assert_that( actual, equal_to( expected ) )
def Subcommands_Format_ExtraConf_BraceOnNewLine_test( app ): WaitUntilCompleterServerReady( app, 'typescript' ) filepath = PathToTestFile( 'extra_confs', 'func.ts' ) RunTest( app, { 'description': 'Format with an extra conf, braces on new line', 'request': { 'command': 'Format', 'filepath': filepath, 'options': { 'tab_size': 4, 'insert_spaces': True } }, 'expect': { 'response': requests.codes.ok, 'data': has_entries( { 'fixits': contains_exactly( has_entries( { 'chunks': contains_exactly( ChunkMatcher( matches_regexp( '\n?\n' ), LocationMatcher( filepath, 1, 19 ), LocationMatcher( filepath, 1, 20 ) ), ChunkMatcher( ' ', LocationMatcher( filepath, 2, 1 ), LocationMatcher( filepath, 2, 1 ) ), ) } ) ) } ) } } )
def WaitUntilCsCompleterIsReady( app, filepath, wait_for_diags = True ): WaitUntilCompleterServerReady( app, 'cs' ) # Omnisharp isn't ready when it says it is, so wait until Omnisharp returns # at least one diagnostic multiple times. if not wait_for_diags: # Wait a fixed amount of time, because there's no reliable way to # know Roslyn is actually ready. time.sleep( 15 ) return success_count = 0 for reraise_error in [ False ] * 39 + [ True ]: try: if len( GetDiagnostics( app, filepath ) ) == 0: raise RuntimeError( "No diagnostic" ) success_count += 1 if success_count > 2: break except Exception: success_count = 0 if reraise_error: raise time.sleep( .5 ) else: raise RuntimeError( "Never was ready" )
def DebugInfo_ServerIsRunning_test( app ): filepath = PathToTestFile( 'testy', 'Program.cs' ) contents = ReadFile( filepath ) event_data = BuildRequest( filepath = filepath, filetype = 'cs', contents = contents, event_name = 'FileReadyToParse' ) app.post_json( '/event_notification', event_data ) WaitUntilCompleterServerReady( app, 'cs' ) request_data = BuildRequest( filepath = filepath, filetype = 'cs' ) assert_that( app.post_json( '/debug_info', request_data ).json, has_entry( 'completer', has_entries( { 'name': 'C#', 'servers': contains_exactly( has_entries( { 'name': 'OmniSharp', 'is_running': True, 'executable': instance_of( str ), 'pid': instance_of( int ), 'address': instance_of( str ), 'port': instance_of( int ), 'logfiles': contains_exactly( instance_of( str ), instance_of( str ) ), 'extras': contains_exactly( has_entries( { 'key': 'solution', 'value': instance_of( str ) } ) ) } ) ), 'items': empty() } ) ) )
def StartRustCompleterServerInDirectory(app, directory): app.post_json( '/event_notification', BuildRequest(filepath=os.path.join(directory, 'main.rs'), event_name='FileReadyToParse', filetype='rust')) WaitUntilCompleterServerReady(app, 'rust')
def test_GenericLSPCompleter_DebugInfo_CustomRoot(self, app, *args): test_file = PathToTestFile('generic_server', 'foo', 'bar', 'baz', 'test_file') request = BuildRequest(filepath=test_file, filetype='foo', line_num=1, column_num=1, contents='', event_name='FileReadyToParse') app.post_json('/event_notification', request) WaitUntilCompleterServerReady(app, 'foo') request.pop('event_name') response = app.post_json('/debug_info', request).json assert_that( response, has_entry( 'completer', has_entries({ 'name': 'GenericLSP', 'servers': contains_exactly( has_entries({ 'name': 'fooCompleter', 'is_running': instance_of(bool), 'executable': contains_exactly(instance_of(str), instance_of(str), instance_of(str)), 'address': None, 'port': None, 'pid': instance_of(int), 'logfiles': contains_exactly(instance_of(str)), 'extras': contains_exactly( has_entries({ 'key': 'Server State', 'value': instance_of(str), }), has_entries({ 'key': 'Project Directory', 'value': PathToTestFile('generic_server', 'foo'), }), has_entries({ 'key': 'Settings', 'value': '{}' }), ) })), })))
def WrapOmniSharpServer(app, filepath): global shared_filepaths if filepath not in shared_filepaths: StartCompleterServer(app, 'cs', filepath) shared_filepaths.append(filepath) WaitUntilCompleterServerReady(app, 'cs') yield
def Subcommands_Format_Range_Tabs_test(app): WaitUntilCompleterServerReady(app, 'typescript') filepath = PathToTestFile('test.ts') RunTest( app, { 'description': 'Formatting is applied on some part of the file ' 'with tabs instead of spaces', 'request': { 'command': 'Format', 'filepath': filepath, 'range': { 'start': { 'line_num': 6, 'column_num': 3, }, 'end': { 'line_num': 11, 'column_num': 6 } }, 'options': { 'tab_size': 4, 'insert_spaces': False } }, 'expect': { 'response': requests.codes.ok, 'data': has_entries({ 'fixits': contains_exactly( has_entries({ 'chunks': contains_exactly( ChunkMatcher('\t', LocationMatcher(filepath, 6, 1), LocationMatcher(filepath, 6, 3)), ChunkMatcher('\t\t', LocationMatcher(filepath, 7, 1), LocationMatcher(filepath, 7, 5)), ChunkMatcher('\t\t\t', LocationMatcher(filepath, 8, 1), LocationMatcher(filepath, 8, 7)), ChunkMatcher('\t\t\t', LocationMatcher(filepath, 9, 1), LocationMatcher(filepath, 9, 7)), ChunkMatcher('\t\t', LocationMatcher(filepath, 10, 1), LocationMatcher(filepath, 10, 5)), ChunkMatcher('\t', LocationMatcher(filepath, 11, 1), LocationMatcher(filepath, 11, 3)), ) })) }) } })
def setUpPackage(): """Initializes the ycmd server as a WebTest application that will be shared by all tests using the SharedYcmd decorator in this package. Additional configuration that is common to these tests, like starting a semantic subserver, should be done here.""" global shared_app shared_app = SetUpApp() WaitUntilCompleterServerReady(shared_app, 'rust')
def Subcommands_RestartServer_PidChanges_test( app ): filepath = PathToTestFile( 'testy', 'GotoTestCase.cs' ) contents = ReadFile( filepath ) event_data = BuildRequest( filepath = filepath, filetype = 'cs', contents = contents, event_name = 'FileReadyToParse' ) app.post_json( '/event_notification', event_data ) try: WaitUntilCompleterServerReady( app, 'cs' ) def GetPid(): request_data = BuildRequest( filetype = 'cs', filepath = filepath ) debug_info = app.post_json( '/debug_info', request_data ).json return debug_info[ "completer" ][ "servers" ][ 0 ][ "pid" ] old_pid = GetPid() app.post_json( '/run_completer_command', BuildRequest( filetype = 'cs', filepath = filepath, command_arguments = [ 'RestartServer' ] ) ) WaitUntilCompleterServerReady( app, 'cs' ) new_pid = GetPid() assert old_pid != new_pid, '%r == %r' % ( old_pid, new_pid ) finally: app.post_json( '/run_completer_command', BuildRequest( filetype = 'cs', filepath = filepath, command_arguments = [ 'StopServer' ] ) )
def setUpPackage(): """Initializes the ycmd server as a WebTest application that will be shared by all tests using the SharedYcmd decorator in this package. Additional configuration that is common to these tests, like starting a semantic subserver, should be done here.""" global shared_app, shared_current_dir shared_app = SetUpApp() shared_current_dir = GetCurrentDirectory() os.chdir(PathToTestFile()) WaitUntilCompleterServerReady(shared_app, 'javascript')
def setUpPackage(): """Initializes the ycmd server as a WebTest application that will be shared by all tests using the SharedYcmd decorator in this package. Additional configuration that is common to these tests, like starting a semantic subserver, should be done here.""" global shared_app with patch( 'ycmd.completers.javascript.hook.' 'ShouldEnableTernCompleter', return_value = False ): shared_app = SetUpApp() WaitUntilCompleterServerReady( shared_app, 'javascript' )
def Signature_Help_Available_test(app): request = {'filepath': PathToTestFile('common', 'src', 'main.rs')} app.post_json('/event_notification', CombineRequest(request, { 'event_name': 'FileReadyToParse', 'filetype': 'rust' }), expect_errors=True) WaitUntilCompleterServerReady(app, 'rust') response = app.get('/signature_help_available', {'subserver': 'rust'}).json assert_that(response, SignatureAvailableMatcher('YES'))
def Signature_Help_Available_Disabled_By_User_test(app, *args): request = {'filepath': PathToTestFile('goto.cc')} app.post_json('/event_notification', CombineRequest(request, { 'event_name': 'FileReadyToParse', 'filetype': 'cpp' }), expect_errors=True) WaitUntilCompleterServerReady(app, 'cpp') response = app.get('/signature_help_available', {'subserver': 'cpp'}).json assert_that(response, SignatureAvailableMatcher('NO'))
def EventNotification_OnFileReadyToParse_ProjectFile_cwd_test(app): WaitUntilCompleterServerReady(app, 'javascript') contents = ReadFile(PathToTestFile('simple_test.js')) response = app.post_json('/event_notification', BuildRequest(event_name='FileReadyToParse', contents=contents, filetype='javascript'), expect_errors=True) eq_(response.status_code, requests.codes.ok) assert_that(response.json, empty())
def Subcommands_StopServer_Timeout_test(app): WaitUntilCompleterServerReady(app, 'typescript') app.post_json( '/run_completer_command', BuildRequest(filetype='typescript', command_arguments=['StopServer'])) request_data = BuildRequest(filetype='typescript') assert_that( app.post_json('/debug_info', request_data).json, has_entry( 'completer', has_entry('servers', contains(has_entry('is_running', False)))))
def RunAfterInitialized(app, test): """Performs initialization of clangd server for the file contents specified in the |test| and optionally can run a test and check for its response. Since LSP servers do not start until initialization we need to send a FileReadyToParse request prior to any other request we will make. |test| consists of two parts a 'request' to be made and an optional 'expect' to perform a check on server's response. Request part must contain either a 'content' or 'filepath' element which either contains or points to the source code that will be sent to the server. In addition to that, if |test| also contain a 'route' element, then a follow-up request will be made to the server, with the same file contents and response of that request will be returned. Expect part, if specified, must contain two elements named 'response' and 'data' which are used to check status code and data of the result received from server before returning them to the caller. Example usage: filepath = PathToTestFile( 'foo.cc' ) request = { 'filepath': filepath, 'filetype': 'cpp' } test = { 'request': request } RunAfterInitialized( app, test ) ... """ request = test['request'] contents = (request['contents'] if 'contents' in request else ReadFile(request['filepath'])) response = app.post_json('/event_notification', CombineRequest( request, { 'event_name': 'FileReadyToParse', 'contents': contents, }), expect_errors=True) WaitUntilCompleterServerReady(app, 'cpp') if 'route' in test: expect_errors = 'expect' in test response = app.post_json(test['route'], CombineRequest(request, {'contents': contents}), expect_errors=expect_errors) if 'expect' in test: print("Completer response: {}".format( json.dumps(response.json, indent=2))) eq_(response.status_code, test['expect']['response']) assert_that(response.json, test['expect']['data']) return response.json