From 18aba7a58296440b440daa02d70dfb00e72c236f Mon Sep 17 00:00:00 2001 From: micbou Date: Thu, 9 Jun 2016 13:06:54 +0200 Subject: [PATCH] Implement new debugging information API --- python/ycm/client/debug_info_request.py | 74 ++++++- .../tests/client/debug_info_request_test.py | 184 ++++++++++++++++++ python/ycm/tests/youcompleteme_test.py | 10 +- python/ycm/youcompleteme.py | 13 +- third_party/ycmd | 2 +- 5 files changed, 268 insertions(+), 15 deletions(-) create mode 100644 python/ycm/tests/client/debug_info_request_test.py diff --git a/python/ycm/client/debug_info_request.py b/python/ycm/client/debug_info_request.py index cf6599a7..b908937d 100644 --- a/python/ycm/client/debug_info_request.py +++ b/python/ycm/client/debug_info_request.py @@ -1,4 +1,4 @@ -# Copyright (C) 2016 YouCompleteMe contributors +# Copyright (C) 2016-2017 YouCompleteMe contributors # # This file is part of YouCompleteMe. # @@ -40,9 +40,75 @@ class DebugInfoRequest( BaseRequest ): def Response( self ): - if not self._response: - return 'Server errored, no debug info from server' - return self._response + return _FormatDebugInfoResponse( self._response ) + + +def _FormatDebugInfoResponse( response ): + if not response: + return 'Server errored, no debug info from server\n' + message = _FormatYcmdDebugInfo( response ) + completer = response[ 'completer' ] + if completer: + message += _FormatCompleterDebugInfo( completer ) + return message + + +def _FormatYcmdDebugInfo( ycmd ): + python = ycmd[ 'python' ] + clang = ycmd[ 'clang' ] + message = ( 'Server Python interpreter: {0}\n' + 'Server Python version: {1}\n' + 'Server has Clang support compiled in: {2}\n' + 'Clang version: {3}\n'.format( python[ 'executable' ], + python[ 'version' ], + clang[ 'has_support' ], + clang[ 'version' ] ) ) + extra_conf = ycmd[ 'extra_conf' ] + extra_conf_path = extra_conf[ 'path' ] + if not extra_conf_path: + message += 'No extra configuration file found\n' + elif not extra_conf[ 'is_loaded' ]: + message += ( 'Extra configuration file found but not loaded\n' + 'Extra configuration path: {0}\n'.format( extra_conf_path ) ) + else: + message += ( 'Extra configuration file found and loaded\n' + 'Extra configuration path: {0}\n'.format( extra_conf_path ) ) + return message + + +def _FormatCompleterDebugInfo( completer ): + message = '{0} completer debug information:\n'.format( completer[ 'name' ] ) + for server in completer[ 'servers' ]: + name = server[ 'name' ] + if server[ 'is_running' ]: + address = server[ 'address' ] + port = server[ 'port' ] + if address and port: + message += ' {0} running at: http://{1}:{2}\n'.format( name, + address, + port ) + else: + message += ' {0} running\n'.format( name ) + message += ' {0} process ID: {1}\n'.format( name, server[ 'pid' ] ) + else: + message += ' {0} not running\n'.format( name ) + message += ' {0} executable: {1}\n'.format( name, server[ 'executable'] ) + logfiles = server[ 'logfiles' ] + if logfiles: + message += ' {0} logfiles:\n'.format( name ) + for logfile in logfiles: + message += ' {0}\n'.format( logfile ) + else: + message += ' No logfiles available\n' + if 'extras' in server: + for extra in server[ 'extras' ]: + message += ' {0} {1}: {2}\n'.format( name, + extra[ 'key' ], + extra[ 'value' ] ) + for item in completer[ 'items' ]: + message += ' {0}: {1}\n'.format( item[ 'key' ].capitalize(), + item[ 'value' ] ) + return message def SendDebugInfoRequest(): diff --git a/python/ycm/tests/client/debug_info_request_test.py b/python/ycm/tests/client/debug_info_request_test.py new file mode 100644 index 00000000..4ec6aa42 --- /dev/null +++ b/python/ycm/tests/client/debug_info_request_test.py @@ -0,0 +1,184 @@ +# Copyright (C) 2017 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 . + +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 copy import deepcopy +from hamcrest import assert_that, contains_string, equal_to + +from ycm.client.debug_info_request import _FormatDebugInfoResponse + + +GENERIC_RESPONSE = { + 'clang': { + 'has_support': True, + 'version': 'Clang version' + }, + 'completer': { + 'items': [ + { + 'key': 'key', + 'value': 'value' + } + ], + 'name': 'Completer name', + 'servers': [ + { + 'address': '127.0.0.1', + 'executable': '/path/to/executable', + 'extras': [ + { + 'key': 'key', + 'value': 'value' + } + ], + 'is_running': True, + 'logfiles': [ + '/path/to/stdout/logfile', + '/path/to/stderr/logfile' + ], + 'name': 'Server name', + 'pid': 12345, + 'port': 1234 + } + ] + }, + 'extra_conf': { + 'is_loaded': False, + 'path': '/path/to/extra/conf' + }, + 'python': { + 'executable': '/path/to/python/interpreter', + 'version': 'Python version' + } +} + + +def FormatDebugInfoResponse_NoResponse_test(): + assert_that( + _FormatDebugInfoResponse( None ), + equal_to( 'Server errored, no debug info from server\n' ) + ) + + +def FormatDebugInfoResponse_NoExtraConf_test(): + response = deepcopy( GENERIC_RESPONSE ) + response[ 'extra_conf' ].update( { + 'is_loaded': False, + 'path': None + } ) + assert_that( + _FormatDebugInfoResponse( response ), + contains_string( + 'No extra configuration file found\n' + ) + ) + + +def FormatDebugInfoResponse_ExtraConfFoundButNotLoaded_test(): + response = deepcopy( GENERIC_RESPONSE ) + response[ 'extra_conf' ].update( { + 'is_loaded': False, + 'path': '/path/to/extra/conf' + } ) + assert_that( + _FormatDebugInfoResponse( response ), + contains_string( + 'Extra configuration file found but not loaded\n' + 'Extra configuration path: /path/to/extra/conf\n' + ) + ) + + +def FormatDebugInfoResponse_ExtraConfFoundAndLoaded_test(): + response = deepcopy( GENERIC_RESPONSE ) + response[ 'extra_conf' ].update( { + 'is_loaded': True, + 'path': '/path/to/extra/conf' + } ) + assert_that( + _FormatDebugInfoResponse( response ), + contains_string( + 'Extra configuration file found and loaded\n' + 'Extra configuration path: /path/to/extra/conf\n' + ) + ) + + +def FormatDebugInfoResponse_Completer_ServerRunningWithHost_test(): + response = deepcopy( GENERIC_RESPONSE ) + assert_that( + _FormatDebugInfoResponse( response ), + contains_string( + 'Completer name completer debug information:\n' + ' Server name running at: http://127.0.0.1:1234\n' + ' Server name process ID: 12345\n' + ' Server name executable: /path/to/executable\n' + ' Server name logfiles:\n' + ' /path/to/stdout/logfile\n' + ' /path/to/stderr/logfile\n' + ' Server name key: value\n' + ' Key: value\n' + ) + ) + + +def FormatDebugInfoResponse_Completer_ServerRunningWithoutHost_test(): + response = deepcopy( GENERIC_RESPONSE ) + response[ 'completer' ][ 'servers' ][ 0 ].update( { + 'address': None, + 'port': None + } ) + assert_that( + _FormatDebugInfoResponse( response ), + contains_string( + 'Completer name completer debug information:\n' + ' Server name running\n' + ' Server name process ID: 12345\n' + ' Server name executable: /path/to/executable\n' + ' Server name logfiles:\n' + ' /path/to/stdout/logfile\n' + ' /path/to/stderr/logfile\n' + ' Server name key: value\n' + ' Key: value\n' + ) + ) + + +def FormatDebugInfoResponse_Completer_ServerNotRunningWithNoLogfiles_test(): + response = deepcopy( GENERIC_RESPONSE ) + response[ 'completer' ][ 'servers' ][ 0 ].update( { + 'is_running': False, + 'logfiles': [] + } ) + assert_that( + _FormatDebugInfoResponse( response ), + contains_string( + 'Completer name completer debug information:\n' + ' Server name not running\n' + ' Server name executable: /path/to/executable\n' + ' No logfiles available\n' + ' Server name key: value\n' + ' Key: value\n' + ) + ) diff --git a/python/ycm/tests/youcompleteme_test.py b/python/ycm/tests/youcompleteme_test.py index be5d762a..a43baf95 100644 --- a/python/ycm/tests/youcompleteme_test.py +++ b/python/ycm/tests/youcompleteme_test.py @@ -1,4 +1,4 @@ -# Copyright (C) 2016 YouCompleteMe contributors +# Copyright (C) 2016-2017 YouCompleteMe contributors # # This file is part of YouCompleteMe. # @@ -23,7 +23,6 @@ from future import standard_library standard_library.install_aliases() from builtins import * # noqa -from ycm.tests import StopServer from ycm.tests.test_utils import ( ExtendedMock, MockVimBuffers, MockVimModule, VimBuffer ) MockVimModule() @@ -34,7 +33,7 @@ from hamcrest import ( assert_that, contains, empty, is_in, is_not, has_length, matches_regexp ) from mock import call, MagicMock, patch -from ycm.tests import YouCompleteMeInstance +from ycm.tests import StopServer, YouCompleteMeInstance from ycmd.responses import ServerError @@ -149,8 +148,11 @@ def YouCompleteMe_DebugInfo_ServerRunning_test( ycm ): ycm.DebugInfo(), matches_regexp( 'Client logfile: .+\n' + 'Server Python interpreter: .+\n' + 'Server Python version: .+\n' 'Server has Clang support compiled in: (True|False)\n' - '(Clang version: .+\n)?' + 'Clang version: .+\n' + 'No extra configuration file found\n' 'Server running at: .+\n' 'Server process ID: \d+\n' 'Server logfiles:\n' diff --git a/python/ycm/youcompleteme.py b/python/ycm/youcompleteme.py index 0116ff0f..6bd0a82b 100644 --- a/python/ycm/youcompleteme.py +++ b/python/ycm/youcompleteme.py @@ -1,5 +1,5 @@ # Copyright (C) 2011-2012 Google Inc. -# 2016 YouCompleteMe contributors +# 2016-2017 YouCompleteMe contributors # # This file is part of YouCompleteMe. # @@ -650,11 +650,12 @@ class YouCompleteMe( object ): if self.IsServerAlive(): debug_info += SendDebugInfoRequest() else: - debug_info += 'Server crashed, no debug info from server' - debug_info += '\nServer running at: {0}\n'.format( - BaseRequest.server_location ) - debug_info += 'Server process ID: {0}\n'.format( self._server_popen.pid ) - if self._server_stderr or self._server_stdout: + debug_info += 'Server crashed, no debug info from server\n' + debug_info += ( + 'Server running at: {0}\n' + 'Server process ID: {1}\n'.format( BaseRequest.server_location, + self._server_popen.pid ) ) + if self._server_stdout and self._server_stderr: debug_info += ( 'Server logfiles:\n' ' {0}\n' ' {1}'.format( self._server_stdout, diff --git a/third_party/ycmd b/third_party/ycmd index d19f9c5e..ec4f3356 160000 --- a/third_party/ycmd +++ b/third_party/ycmd @@ -1 +1 @@ -Subproject commit d19f9c5e8e5ca47a9784a78a3aa39a49f8c3e7c6 +Subproject commit ec4f335676351eb89e554d0c0b45f01e22243e1a