Merge pull request #42 from puremourning/test-framework
Fix and test breakpoint issues
This commit is contained in:
commit
28088c991d
17 changed files with 458 additions and 256 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -13,3 +13,5 @@ package/
|
||||||
README.md.orig.*
|
README.md.orig.*
|
||||||
README.md.toc.*
|
README.md.toc.*
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
*.vimspector.log
|
||||||
|
support/test/csharp/*.exe*
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,9 @@ let current_compiler = "vimspector_test"
|
||||||
setlocal errorformat=
|
setlocal errorformat=
|
||||||
\Found\ errors\ in\ %f:%.%#:
|
\Found\ errors\ in\ %f:%.%#:
|
||||||
|
|
||||||
let &l:makeprg=fnamemodify( findfile( 'run_tests', '.;' ), ':p' )
|
let s:run_tests = findfile( 'run_tests', '.;' )
|
||||||
\ . ' $* 2>&1'
|
let s:root_dir = fnamemodify( s:run_tests, ':h' )
|
||||||
|
let &l:makeprg=fnamemodify( s:run_tests, ':p' ) . ' $* 2>&1'
|
||||||
|
|
||||||
let s:make_cmd = get( g:, 'vimspector_test_make_cmd', 'Make' )
|
let s:make_cmd = get( g:, 'vimspector_test_make_cmd', 'Make' )
|
||||||
|
|
||||||
|
|
@ -86,17 +87,35 @@ function! s:RunTestUnderCursor()
|
||||||
echo "Running test '" . l:test_func_name . "'"
|
echo "Running test '" . l:test_func_name . "'"
|
||||||
|
|
||||||
let l:test_arg = expand( '%:p:t' ) . ':' . l:test_func_name
|
let l:test_arg = expand( '%:p:t' ) . ':' . l:test_func_name
|
||||||
execute s:make_cmd . ' ' . l:test_arg
|
let l:cwd = getcwd()
|
||||||
|
execute 'lcd ' . s:root_dir
|
||||||
|
try
|
||||||
|
execute s:make_cmd . ' ' . l:test_arg
|
||||||
|
finally
|
||||||
|
execute 'lcd ' . l:cwd
|
||||||
|
endtry
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:RunTest()
|
function! s:RunTest()
|
||||||
update
|
update
|
||||||
execute s:make_cmd . ' %:p:t'
|
let l:cwd = getcwd()
|
||||||
|
execute 'lcd ' . s:root_dir
|
||||||
|
try
|
||||||
|
execute s:make_cmd . ' %:p:t'
|
||||||
|
finally
|
||||||
|
execute 'lcd ' . l:cwd
|
||||||
|
endtry
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:RunAllTests()
|
function! s:RunAllTests()
|
||||||
update
|
update
|
||||||
execute s:make_cmd
|
let l:cwd = getcwd()
|
||||||
|
execute 'lcd ' . s:root_dir
|
||||||
|
try
|
||||||
|
execute s:make_cmd
|
||||||
|
finally
|
||||||
|
execute 'lcd ' . l:cwd
|
||||||
|
endtry
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
if ! has( 'gui_running' )
|
if ! has( 'gui_running' )
|
||||||
|
|
|
||||||
|
|
@ -15,16 +15,30 @@
|
||||||
|
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
|
||||||
|
import abc
|
||||||
import vim
|
import vim
|
||||||
import os
|
import os
|
||||||
|
import logging
|
||||||
|
|
||||||
import json
|
import json
|
||||||
from vimspector import utils
|
from vimspector import utils
|
||||||
|
|
||||||
|
|
||||||
|
class ServerBreakpointHandler( object ):
|
||||||
|
@abc.abstractmethod
|
||||||
|
def ClearBreakpoints( self ):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def AddBreakpoints( self, source, message ):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class ProjectBreakpoints( object ):
|
class ProjectBreakpoints( object ):
|
||||||
def __init__( self ):
|
def __init__( self ):
|
||||||
self._connection = None
|
self._connection = None
|
||||||
|
self._logger = logging.getLogger( __name__ )
|
||||||
|
utils.SetUpLogging( self._logger )
|
||||||
|
|
||||||
# These are the user-entered breakpoints.
|
# These are the user-entered breakpoints.
|
||||||
self._line_breakpoints = defaultdict( list )
|
self._line_breakpoints = defaultdict( list )
|
||||||
|
|
@ -55,6 +69,7 @@ class ProjectBreakpoints( object ):
|
||||||
self._exceptionBreakpoints = None
|
self._exceptionBreakpoints = None
|
||||||
self._server_capabilities = {}
|
self._server_capabilities = {}
|
||||||
self._connection = None
|
self._connection = None
|
||||||
|
self.UpdateUI()
|
||||||
|
|
||||||
# for each breakpoint:
|
# for each breakpoint:
|
||||||
# clear its resolved status
|
# clear its resolved status
|
||||||
|
|
@ -94,6 +109,12 @@ class ProjectBreakpoints( object ):
|
||||||
|
|
||||||
def ClearBreakpoints( self ):
|
def ClearBreakpoints( self ):
|
||||||
# These are the user-entered breakpoints.
|
# These are the user-entered breakpoints.
|
||||||
|
for file_name, breakpoints in self._line_breakpoints.items():
|
||||||
|
for bp in breakpoints:
|
||||||
|
if 'sign_id' in bp:
|
||||||
|
vim.command( 'sign unplace {0} group=VimspectorBP'.format(
|
||||||
|
bp[ 'sign_id' ] ) )
|
||||||
|
|
||||||
self._line_breakpoints = defaultdict( list )
|
self._line_breakpoints = defaultdict( list )
|
||||||
self._func_breakpoints = []
|
self._func_breakpoints = []
|
||||||
self._exceptionBreakpoints = None
|
self._exceptionBreakpoints = None
|
||||||
|
|
@ -108,16 +129,26 @@ class ProjectBreakpoints( object ):
|
||||||
return
|
return
|
||||||
|
|
||||||
found_bp = False
|
found_bp = False
|
||||||
|
action = 'New'
|
||||||
for index, bp in enumerate( self._line_breakpoints[ file_name ] ):
|
for index, bp in enumerate( self._line_breakpoints[ file_name ] ):
|
||||||
if bp[ 'line' ] == line:
|
if bp[ 'line' ] == line:
|
||||||
found_bp = True
|
found_bp = True
|
||||||
if bp[ 'state' ] == 'ENABLED':
|
if bp[ 'state' ] == 'ENABLED' and not self._connection:
|
||||||
bp[ 'state' ] = 'DISABLED'
|
bp[ 'state' ] = 'DISABLED'
|
||||||
|
action = 'Disable'
|
||||||
else:
|
else:
|
||||||
if 'sign_id' in bp:
|
if 'sign_id' in bp:
|
||||||
vim.command( 'sign unplace {0} group=VimspectorBP'.format(
|
vim.command( 'sign unplace {0} group=VimspectorBP'.format(
|
||||||
bp[ 'sign_id' ] ) )
|
bp[ 'sign_id' ] ) )
|
||||||
del self._line_breakpoints[ file_name ][ index ]
|
del self._line_breakpoints[ file_name ][ index ]
|
||||||
|
action = 'Delete'
|
||||||
|
break
|
||||||
|
|
||||||
|
self._logger.debug( "Toggle found bp at {}:{} ? {} ({})".format(
|
||||||
|
file_name,
|
||||||
|
line,
|
||||||
|
found_bp,
|
||||||
|
action ) )
|
||||||
|
|
||||||
if not found_bp:
|
if not found_bp:
|
||||||
self._line_breakpoints[ file_name ].append( {
|
self._line_breakpoints[ file_name ].append( {
|
||||||
|
|
@ -157,23 +188,22 @@ class ProjectBreakpoints( object ):
|
||||||
|
|
||||||
|
|
||||||
def SendBreakpoints( self ):
|
def SendBreakpoints( self ):
|
||||||
if not self._breakpoints_handler:
|
assert self._breakpoints_handler is not None
|
||||||
def handler( source, msg ):
|
|
||||||
return self._ShowBreakpoints()
|
# Clear any existing breakpoints prior to sending new ones
|
||||||
else:
|
self._breakpoints_handler.ClearBreakpoints()
|
||||||
handler = self._breakpoints_handler
|
|
||||||
|
|
||||||
for file_name, line_breakpoints in self._line_breakpoints.items():
|
for file_name, line_breakpoints in self._line_breakpoints.items():
|
||||||
breakpoints = []
|
breakpoints = []
|
||||||
for bp in line_breakpoints:
|
for bp in line_breakpoints:
|
||||||
if bp[ 'state' ] != 'ENABLED':
|
|
||||||
continue
|
|
||||||
|
|
||||||
if 'sign_id' in bp:
|
if 'sign_id' in bp:
|
||||||
vim.command( 'sign unplace {0} group=VimspectorBP'.format(
|
vim.command( 'sign unplace {0} group=VimspectorBP'.format(
|
||||||
bp[ 'sign_id' ] ) )
|
bp[ 'sign_id' ] ) )
|
||||||
del bp[ 'sign_id' ]
|
del bp[ 'sign_id' ]
|
||||||
|
|
||||||
|
if bp[ 'state' ] != 'ENABLED':
|
||||||
|
continue
|
||||||
|
|
||||||
breakpoints.append( { 'line': bp[ 'line' ] } )
|
breakpoints.append( { 'line': bp[ 'line' ] } )
|
||||||
|
|
||||||
source = {
|
source = {
|
||||||
|
|
@ -182,7 +212,7 @@ class ProjectBreakpoints( object ):
|
||||||
}
|
}
|
||||||
|
|
||||||
self._connection.DoRequest(
|
self._connection.DoRequest(
|
||||||
lambda msg: handler( source, msg ),
|
lambda msg: self._breakpoints_handler.AddBreakpoints( source, msg ),
|
||||||
{
|
{
|
||||||
'command': 'setBreakpoints',
|
'command': 'setBreakpoints',
|
||||||
'arguments': {
|
'arguments': {
|
||||||
|
|
@ -195,7 +225,7 @@ class ProjectBreakpoints( object ):
|
||||||
|
|
||||||
if self._server_capabilities.get( 'supportsFunctionBreakpoints' ):
|
if self._server_capabilities.get( 'supportsFunctionBreakpoints' ):
|
||||||
self._connection.DoRequest(
|
self._connection.DoRequest(
|
||||||
lambda msg: handler( None, msg ),
|
lambda msg: self._breakpoints_handler.AddBreakpoints( None, msg ),
|
||||||
{
|
{
|
||||||
'command': 'setFunctionBreakpoints',
|
'command': 'setFunctionBreakpoints',
|
||||||
'arguments': {
|
'arguments': {
|
||||||
|
|
|
||||||
|
|
@ -128,23 +128,11 @@ class CodeView( object ):
|
||||||
# Not found. Assume new
|
# Not found. Assume new
|
||||||
self.AddBreakpoints( None, [ bp ] )
|
self.AddBreakpoints( None, [ bp ] )
|
||||||
|
|
||||||
def DeleteBreakpoint( self, bp ):
|
|
||||||
if 'id' not in bp:
|
|
||||||
return
|
|
||||||
|
|
||||||
for _, breakpoint_list in self._breakpoints.items():
|
|
||||||
for index, breakpoint in enumerate( breakpoint_list ):
|
|
||||||
if 'id' in breakpoint and breakpoint[ 'id' ] == bp[ 'id' ]:
|
|
||||||
del breakpoint_list[ index ]
|
|
||||||
return
|
|
||||||
|
|
||||||
# Not found. Shrug.
|
|
||||||
|
|
||||||
def _UndisplaySigns( self ):
|
def _UndisplaySigns( self ):
|
||||||
for sign_id in self._signs[ 'breakpoints' ]:
|
for sign_id in self._signs[ 'breakpoints' ]:
|
||||||
vim.command( 'sign unplace {} group=VimspectorCode'.format( sign_id ) )
|
vim.command( 'sign unplace {} group=VimspectorCode'.format( sign_id ) )
|
||||||
|
|
||||||
self._signs[ 'breakpoints' ].clear()
|
self._signs[ 'breakpoints' ] = []
|
||||||
|
|
||||||
def ClearBreakpoints( self ):
|
def ClearBreakpoints( self ):
|
||||||
self._UndisplaySigns()
|
self._UndisplaySigns()
|
||||||
|
|
@ -169,7 +157,7 @@ class CodeView( object ):
|
||||||
sign_id,
|
sign_id,
|
||||||
breakpoint[ 'line' ],
|
breakpoint[ 'line' ],
|
||||||
'vimspectorBP' if breakpoint[ 'verified' ]
|
'vimspectorBP' if breakpoint[ 'verified' ]
|
||||||
else 'vimspectorBPDisabled',
|
else 'vimspectorBPDisabled',
|
||||||
file_name ) )
|
file_name ) )
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ import json
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import shlex
|
import shlex
|
||||||
|
import traceback
|
||||||
|
|
||||||
from vimspector import ( breakpoints,
|
from vimspector import ( breakpoints,
|
||||||
code,
|
code,
|
||||||
|
|
@ -39,6 +40,7 @@ class DebugSession( object ):
|
||||||
self._logger = logging.getLogger( __name__ )
|
self._logger = logging.getLogger( __name__ )
|
||||||
utils.SetUpLogging( self._logger )
|
utils.SetUpLogging( self._logger )
|
||||||
|
|
||||||
|
self._logger.info( "**** INITIALISING NEW VIMSPECTOR SESSION ****" )
|
||||||
self._logger.info( 'VIMSPECTOR_HOME = %s', VIMSPECTOR_HOME )
|
self._logger.info( 'VIMSPECTOR_HOME = %s', VIMSPECTOR_HOME )
|
||||||
self._logger.info( 'gadgetDir = %s',
|
self._logger.info( 'gadgetDir = %s',
|
||||||
install.GetGadgetDir( VIMSPECTOR_HOME,
|
install.GetGadgetDir( VIMSPECTOR_HOME,
|
||||||
|
|
@ -63,6 +65,8 @@ class DebugSession( object ):
|
||||||
self._server_capabilities = {}
|
self._server_capabilities = {}
|
||||||
|
|
||||||
def Start( self, launch_variables = {} ):
|
def Start( self, launch_variables = {} ):
|
||||||
|
self._logger.info( "User requested start debug session with %s",
|
||||||
|
launch_variables )
|
||||||
self._configuration = None
|
self._configuration = None
|
||||||
self._adapter = None
|
self._adapter = None
|
||||||
|
|
||||||
|
|
@ -162,13 +166,16 @@ class DebugSession( object ):
|
||||||
|
|
||||||
def _StartWithConfiguration( self, configuration, adapter ):
|
def _StartWithConfiguration( self, configuration, adapter ):
|
||||||
def start():
|
def start():
|
||||||
|
self._logger.debug( "Starting debugger from stack context: %s",
|
||||||
|
traceback.format_stack() )
|
||||||
|
|
||||||
self._configuration = configuration
|
self._configuration = configuration
|
||||||
self._adapter = adapter
|
self._adapter = adapter
|
||||||
|
|
||||||
self._logger.info( 'Configuration: {0}'.format( json.dumps(
|
self._logger.info( 'Configuration: %s',
|
||||||
self._configuration ) ) )
|
json.dumps( self._configuration ) )
|
||||||
self._logger.info( 'Adapter: {0}'.format( json.dumps(
|
self._logger.info( 'Adapter: %s',
|
||||||
self._adapter ) ) )
|
json.dumps( self._adapter ) )
|
||||||
|
|
||||||
if not self._uiTab:
|
if not self._uiTab:
|
||||||
self._SetUpUI()
|
self._SetUpUI()
|
||||||
|
|
@ -183,16 +190,23 @@ class DebugSession( object ):
|
||||||
self._outputView.ConnectionUp( self._connection )
|
self._outputView.ConnectionUp( self._connection )
|
||||||
self._breakpoints.ConnectionUp( self._connection )
|
self._breakpoints.ConnectionUp( self._connection )
|
||||||
|
|
||||||
def update_breakpoints( source, message ):
|
class Handler( breakpoints.ServerBreakpointHandler ):
|
||||||
if 'body' not in message:
|
def __init__( self, codeView ):
|
||||||
return
|
self.codeView = codeView
|
||||||
self._codeView.AddBreakpoints( source,
|
|
||||||
message[ 'body' ][ 'breakpoints' ] )
|
|
||||||
self._codeView.ShowBreakpoints()
|
|
||||||
|
|
||||||
self._breakpoints.SetBreakpointsHandler( update_breakpoints )
|
def ClearBreakpoints( self ):
|
||||||
|
self.codeView.ClearBreakpoints()
|
||||||
|
|
||||||
|
def AddBreakpoints( self, source, message ):
|
||||||
|
if 'body' not in message:
|
||||||
|
return
|
||||||
|
self.codeView.AddBreakpoints( source,
|
||||||
|
message[ 'body' ][ 'breakpoints' ] )
|
||||||
|
|
||||||
|
self._breakpoints.SetBreakpointsHandler( Handler( self._codeView ) )
|
||||||
|
|
||||||
if self._connection:
|
if self._connection:
|
||||||
|
self._logger.debug( "_StopDebugAdapter with callback: start" )
|
||||||
self._StopDebugAdapter( start )
|
self._StopDebugAdapter( start )
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
@ -212,6 +226,7 @@ class DebugSession( object ):
|
||||||
if self._connection:
|
if self._connection:
|
||||||
self._connection.OnData( data )
|
self._connection.OnData( data )
|
||||||
|
|
||||||
|
|
||||||
def OnServerStderr( self, data ):
|
def OnServerStderr( self, data ):
|
||||||
self._logger.info( "Server stderr: %s", data )
|
self._logger.info( "Server stderr: %s", data )
|
||||||
if self._outputView:
|
if self._outputView:
|
||||||
|
|
@ -227,22 +242,31 @@ class DebugSession( object ):
|
||||||
self._connection = None
|
self._connection = None
|
||||||
|
|
||||||
def Stop( self ):
|
def Stop( self ):
|
||||||
|
self._logger.debug( "Stop debug adapter with no callback" )
|
||||||
self._StopDebugAdapter()
|
self._StopDebugAdapter()
|
||||||
|
|
||||||
def Reset( self ):
|
def Reset( self ):
|
||||||
if self._connection:
|
if self._connection:
|
||||||
|
self._logger.debug( "Stop debug adapter with callback : self._Reset()" )
|
||||||
self._StopDebugAdapter( lambda: self._Reset() )
|
self._StopDebugAdapter( lambda: self._Reset() )
|
||||||
else:
|
else:
|
||||||
self._Reset()
|
self._Reset()
|
||||||
|
|
||||||
def _Reset( self ):
|
def _Reset( self ):
|
||||||
|
self._logger.info( "Debugging complete." )
|
||||||
if self._uiTab:
|
if self._uiTab:
|
||||||
|
self._logger.debug( "Clearing down UI with stack_trace: %s",
|
||||||
|
traceback.format_stack() )
|
||||||
vim.current.tabpage = self._uiTab
|
vim.current.tabpage = self._uiTab
|
||||||
self._stackTraceView.Reset()
|
self._stackTraceView.Reset()
|
||||||
self._variablesView.Reset()
|
self._variablesView.Reset()
|
||||||
self._outputView.Reset()
|
self._outputView.Reset()
|
||||||
self._codeView.Reset()
|
self._codeView.Reset()
|
||||||
vim.command( 'tabclose!' )
|
vim.command( 'tabclose!' )
|
||||||
|
self._stackTraceView = None
|
||||||
|
self._variablesView = None
|
||||||
|
self._outputView = None
|
||||||
|
self._codeView = None
|
||||||
self._uiTab = None
|
self._uiTab = None
|
||||||
|
|
||||||
# make sure that we're displaying signs in any still-open buffers
|
# make sure that we're displaying signs in any still-open buffers
|
||||||
|
|
@ -312,9 +336,9 @@ class DebugSession( object ):
|
||||||
self._variablesView.ShowBalloon( self._stackTraceView.GetCurrentFrame(),
|
self._variablesView.ShowBalloon( self._stackTraceView.GetCurrentFrame(),
|
||||||
expression )
|
expression )
|
||||||
else:
|
else:
|
||||||
self._logger.debug( 'Winnr {0} is not the code window {1}'.format(
|
self._logger.debug( 'Winnr %s is not the code window %s',
|
||||||
winnr,
|
winnr,
|
||||||
self._codeView._window.number ) )
|
self._codeView._window.number )
|
||||||
|
|
||||||
def ExpandFrameOrThread( self ):
|
def ExpandFrameOrThread( self ):
|
||||||
self._stackTraceView.ExpandFrameOrThread()
|
self._stackTraceView.ExpandFrameOrThread()
|
||||||
|
|
@ -387,8 +411,8 @@ class DebugSession( object ):
|
||||||
persist = True )
|
persist = True )
|
||||||
return
|
return
|
||||||
|
|
||||||
self._logger.info( 'Starting debug adapter with: {0}'.format( json.dumps(
|
self._logger.info( 'Starting debug adapter with: %s',
|
||||||
self._adapter ) ) )
|
json.dumps( self._adapter ) )
|
||||||
|
|
||||||
self._init_complete = False
|
self._init_complete = False
|
||||||
self._on_init_complete_handlers = []
|
self._on_init_complete_handlers = []
|
||||||
|
|
@ -428,13 +452,14 @@ class DebugSession( object ):
|
||||||
|
|
||||||
def _StopDebugAdapter( self, callback = None ):
|
def _StopDebugAdapter( self, callback = None ):
|
||||||
def handler( *args ):
|
def handler( *args ):
|
||||||
vim.eval( 'vimspector#internal#{}#StopDebugSession()'.format(
|
|
||||||
self._connection_type ) )
|
|
||||||
|
|
||||||
if callback:
|
if callback:
|
||||||
|
self._logger.debug( "Setting server exit handler before disconnect" )
|
||||||
assert not self._run_on_server_exit
|
assert not self._run_on_server_exit
|
||||||
self._run_on_server_exit = callback
|
self._run_on_server_exit = callback
|
||||||
|
|
||||||
|
vim.eval( 'vimspector#internal#{}#StopDebugSession()'.format(
|
||||||
|
self._connection_type ) )
|
||||||
|
|
||||||
arguments = {}
|
arguments = {}
|
||||||
if self._server_capabilities.get( 'supportTerminateDebuggee' ):
|
if self._server_capabilities.get( 'supportTerminateDebuggee' ):
|
||||||
arguments[ 'terminateDebugee' ] = True
|
arguments[ 'terminateDebugee' ] = True
|
||||||
|
|
@ -638,6 +663,11 @@ class DebugSession( object ):
|
||||||
# doesn't respond top threads request when attaching via gdbserver. At
|
# doesn't respond top threads request when attaching via gdbserver. At
|
||||||
# least it would apear that way.
|
# least it would apear that way.
|
||||||
#
|
#
|
||||||
|
# As it turns out this is due to a bug in gdbserver which means that
|
||||||
|
# attachment doesn't work due to sending the signal to the process group
|
||||||
|
# leader rather than the process. The workaround is to manually SIGTRAP the
|
||||||
|
# PID.
|
||||||
|
#
|
||||||
if self._launch_complete and self._init_complete:
|
if self._launch_complete and self._init_complete:
|
||||||
for h in self._on_init_complete_handlers:
|
for h in self._on_init_complete_handlers:
|
||||||
h()
|
h()
|
||||||
|
|
@ -719,6 +749,8 @@ class DebugSession( object ):
|
||||||
self._variablesView.Clear()
|
self._variablesView.Clear()
|
||||||
|
|
||||||
def OnServerExit( self, status ):
|
def OnServerExit( self, status ):
|
||||||
|
self._logger.info( "The server has terminated with status %s",
|
||||||
|
status )
|
||||||
self.Clear()
|
self.Clear()
|
||||||
|
|
||||||
self._connection.Reset()
|
self._connection.Reset()
|
||||||
|
|
@ -730,11 +762,14 @@ class DebugSession( object ):
|
||||||
self._ResetServerState()
|
self._ResetServerState()
|
||||||
|
|
||||||
if self._run_on_server_exit:
|
if self._run_on_server_exit:
|
||||||
|
self._logger.debug( "Running server exit handler" )
|
||||||
self._run_on_server_exit()
|
self._run_on_server_exit()
|
||||||
|
else:
|
||||||
|
self._logger.debug( "No server exit handler" )
|
||||||
|
|
||||||
def OnEvent_terminated( self, message ):
|
def OnEvent_terminated( self, message ):
|
||||||
# We will handle this when the server actually exists
|
# We will handle this when the server actually exists
|
||||||
utils.UserMessage( "Debugging was terminated." )
|
utils.UserMessage( "Debugging was terminated by the server." )
|
||||||
|
|
||||||
def OnEvent_output( self, message ):
|
def OnEvent_output( self, message ):
|
||||||
if self._outputView:
|
if self._outputView:
|
||||||
|
|
@ -771,6 +806,9 @@ class DebugSession( object ):
|
||||||
return self._breakpoints.ToggleBreakpoint()
|
return self._breakpoints.ToggleBreakpoint()
|
||||||
|
|
||||||
def ClearBreakpoints( self ):
|
def ClearBreakpoints( self ):
|
||||||
|
if self._connection:
|
||||||
|
self._codeView.ClearBreakpoints()
|
||||||
|
|
||||||
return self._breakpoints.ClearBreakpoints()
|
return self._breakpoints.ClearBreakpoints()
|
||||||
|
|
||||||
def AddFunctionBreakpoint( self, function ):
|
def AddFunctionBreakpoint( self, function ):
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,7 @@ class OutputView( object ):
|
||||||
if 'E516' not in e:
|
if 'E516' not in e:
|
||||||
raise
|
raise
|
||||||
|
|
||||||
self._buffers.clear()
|
self._buffers = {}
|
||||||
|
|
||||||
def _ShowOutput( self, category ):
|
def _ShowOutput( self, category ):
|
||||||
utils.JumpToWindow( self._window )
|
utils.JumpToWindow( self._window )
|
||||||
|
|
|
||||||
|
|
@ -69,8 +69,6 @@ def SetUpCommandBuffer( cmd, name ):
|
||||||
name,
|
name,
|
||||||
cmd ) )
|
cmd ) )
|
||||||
|
|
||||||
UserMessage( 'Bufs: {}'.format( [ int( b ) for b in bufs ] ), persist = True )
|
|
||||||
|
|
||||||
return [ vim.buffers[ b ] for b in bufs ]
|
return [ vim.buffers[ b ] for b in bufs ]
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -227,6 +225,11 @@ def Escape( msg ):
|
||||||
|
|
||||||
|
|
||||||
def UserMessage( msg, persist=False ):
|
def UserMessage( msg, persist=False ):
|
||||||
|
if persist:
|
||||||
|
_logger.warning( 'User Msg: ' + msg )
|
||||||
|
else:
|
||||||
|
_logger.info( 'User Msg: ' + msg )
|
||||||
|
|
||||||
vim.command( 'redraw' )
|
vim.command( 'redraw' )
|
||||||
cmd = 'echom' if persist else 'echo'
|
cmd = 'echom' if persist else 'echo'
|
||||||
for line in msg.split( '\n' ):
|
for line in msg.split( '\n' ):
|
||||||
|
|
@ -283,7 +286,7 @@ def AppendToBuffer( buf, line_or_lines, modified=False ):
|
||||||
except Exception:
|
except Exception:
|
||||||
# There seem to be a lot of Vim bugs that lead to E315, whose help says that
|
# There seem to be a lot of Vim bugs that lead to E315, whose help says that
|
||||||
# this is an internal error. Ignore the error, but write a trace to the log.
|
# this is an internal error. Ignore the error, but write a trace to the log.
|
||||||
logging.getLogger( __name__ ).exception(
|
_logger.exception(
|
||||||
'Internal error while updating buffer %s (%s)', buf.name, buf.number )
|
'Internal error while updating buffer %s (%s)', buf.name, buf.number )
|
||||||
finally:
|
finally:
|
||||||
if not modified:
|
if not modified:
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,9 @@
|
||||||
source lib/shared.vim
|
|
||||||
|
|
||||||
function! SetUp()
|
function! SetUp()
|
||||||
if exists ( 'g:loaded_vimpector' )
|
call vimspector#test#setup#SetUpWithMappings( v:none )
|
||||||
unlet g:loaded_vimpector
|
|
||||||
endif
|
|
||||||
|
|
||||||
source vimrc
|
|
||||||
|
|
||||||
" This is a bit of a hack
|
|
||||||
runtime! plugin/**/*.vim
|
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! ClearDown()
|
function! ClearDown()
|
||||||
if exists( '*vimspector#internal#state#Reset' )
|
call vimspector#test#setup#ClearDown()
|
||||||
call vimspector#internal#state#Reset()
|
|
||||||
endif
|
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! SetUp_Test_Mappings_Are_Added_HUMAN()
|
function! SetUp_Test_Mappings_Are_Added_HUMAN()
|
||||||
|
|
@ -62,40 +51,27 @@ function! Test_Signs_Placed_Using_API_Are_Shown()
|
||||||
call vimspector#ToggleBreakpoint()
|
call vimspector#ToggleBreakpoint()
|
||||||
|
|
||||||
call assert_true( exists( '*vimspector#ToggleBreakpoint' ) )
|
call assert_true( exists( '*vimspector#ToggleBreakpoint' ) )
|
||||||
|
call vimspector#test#signs#AssertSignGroupSingletonAtLine( 'VimspectorBP',
|
||||||
let signs = sign_getplaced( '%', {
|
\ line( '.' ),
|
||||||
\ 'group': 'VimspectorBP',
|
\ 'vimspectorBP' )
|
||||||
\ 'line': line( '.' )
|
|
||||||
\ } )
|
|
||||||
|
|
||||||
call assert_equal( 1, len( signs ) )
|
|
||||||
call assert_equal( 1, len( signs[ 0 ].signs ) )
|
|
||||||
call assert_equal( 'vimspectorBP', signs[ 0 ].signs[ 0 ].name )
|
|
||||||
|
|
||||||
" Disable breakpoint
|
" Disable breakpoint
|
||||||
call vimspector#ToggleBreakpoint()
|
call vimspector#ToggleBreakpoint()
|
||||||
|
call vimspector#test#signs#AssertSignGroupSingletonAtLine(
|
||||||
let signs = sign_getplaced( '%', {
|
\ 'VimspectorBP',
|
||||||
\ 'group': 'VimspectorBP',
|
\ line( '.' ),
|
||||||
\ 'line': line( '.' )
|
\ 'vimspectorBPDisabled' )
|
||||||
\ } )
|
|
||||||
|
|
||||||
call assert_equal( 1, len( signs ) )
|
|
||||||
call assert_equal( 1, len( signs[ 0 ].signs ) )
|
|
||||||
call assert_equal( 'vimspectorBPDisabled', signs[ 0 ].signs[ 0 ].name )
|
|
||||||
|
|
||||||
" Remove breakpoint
|
" Remove breakpoint
|
||||||
call vimspector#ToggleBreakpoint()
|
call vimspector#ToggleBreakpoint()
|
||||||
|
|
||||||
let signs = sign_getplaced( '%', {
|
call vimspector#test#signs#AssertSignGroupEmptyAtLine( 'VimspectorBP',
|
||||||
\ 'group': 'VimspectorBP',
|
\ line( '.' ) )
|
||||||
\ 'line': line( '.' )
|
|
||||||
\ } )
|
|
||||||
|
|
||||||
call assert_equal( 1, len( signs ) )
|
|
||||||
call assert_equal( 0, len( signs[ 0 ].signs ) )
|
|
||||||
|
|
||||||
call vimspector#ClearBreakpoints()
|
call vimspector#ClearBreakpoints()
|
||||||
|
call vimspector#test#signs#AssertSignGroupEmpty( 'VimspectorBP' )
|
||||||
|
call vimspector#test#signs#AssertSignGroupEmpty( 'VimspectorCode' )
|
||||||
|
|
||||||
%bwipeout!
|
%bwipeout!
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
@ -106,54 +82,34 @@ endfunction
|
||||||
function! Test_Use_Mappings_HUMAN()
|
function! Test_Use_Mappings_HUMAN()
|
||||||
lcd testdata/cpp/simple
|
lcd testdata/cpp/simple
|
||||||
edit simple.cpp
|
edit simple.cpp
|
||||||
|
call setpos( '.', [ 0, 15, 1 ] )
|
||||||
|
|
||||||
15
|
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'simple.cpp', 15, 1 )
|
||||||
call assert_equal( 15, line( '.' ) )
|
call vimspector#test#signs#AssertSignGroupEmptyAtLine( 'VimspectorBP', 15 )
|
||||||
|
|
||||||
" Add the breakpoing
|
" Add the breakpoint
|
||||||
call feedkeys( "\<F9>", 'xt' )
|
call feedkeys( "\<F9>", 'xt' )
|
||||||
|
call vimspector#test#signs#AssertSignGroupSingletonAtLine( 'VimspectorBP',
|
||||||
let signs = sign_getplaced( '%', {
|
\ 15,
|
||||||
\ 'group': 'VimspectorBP',
|
\ 'vimspectorBP' )
|
||||||
\ 'line': line( '.' )
|
|
||||||
\ } )
|
|
||||||
|
|
||||||
call assert_equal( 1, len( signs ), 1 )
|
|
||||||
call assert_equal( 1, len( signs[ 0 ].signs ), 1 )
|
|
||||||
call assert_equal( 'vimspectorBP', signs[ 0 ].signs[ 0 ].name )
|
|
||||||
|
|
||||||
" Disable the breakpoint
|
" Disable the breakpoint
|
||||||
call feedkeys( "\<F9>", 'xt' )
|
call feedkeys( "\<F9>", 'xt' )
|
||||||
|
call vimspector#test#signs#AssertSignGroupSingletonAtLine(
|
||||||
let signs = sign_getplaced( '%', {
|
\ 'VimspectorBP',
|
||||||
\ 'group': 'VimspectorBP',
|
\ 15,
|
||||||
\ 'line': line( '.' )
|
\ 'vimspectorBPDisabled' )
|
||||||
\ } )
|
|
||||||
call assert_equal( 1, len( signs ), 1 )
|
|
||||||
call assert_equal( 1, len( signs[ 0 ].signs ), 1 )
|
|
||||||
call assert_equal( 'vimspectorBPDisabled', signs[ 0 ].signs[ 0 ].name )
|
|
||||||
|
|
||||||
" Delete the breakpoint
|
" Delete the breakpoint
|
||||||
call feedkeys( "\<F9>", 'xt' )
|
call feedkeys( "\<F9>", 'xt' )
|
||||||
|
call vimspector#test#signs#AssertSignGroupEmptyAtLine( 'VimspectorBP', 15 )
|
||||||
let signs = sign_getplaced( '%', {
|
|
||||||
\ 'group': 'VimspectorBP',
|
|
||||||
\ 'line': line( '.' )
|
|
||||||
\ } )
|
|
||||||
call assert_equal( 1, len( signs ), 1 )
|
|
||||||
call assert_equal( 0, len( signs[ 0 ].signs ) )
|
|
||||||
|
|
||||||
" Add it again
|
" Add it again
|
||||||
call feedkeys( "\<F9>", 'xt' )
|
call feedkeys( "\<F9>", 'xt' )
|
||||||
|
call vimspector#test#signs#AssertSignGroupSingletonAtLine(
|
||||||
let signs = sign_getplaced( '%', {
|
\ 'VimspectorBP',
|
||||||
\ 'group': 'VimspectorBP',
|
\ 15,
|
||||||
\ 'line': line( '.' )
|
\ 'vimspectorBP' )
|
||||||
\ } )
|
|
||||||
|
|
||||||
call assert_equal( 1, len( signs ), 1 )
|
|
||||||
call assert_equal( 1, len( signs[ 0 ].signs ), 1 )
|
|
||||||
call assert_equal( 'vimspectorBP', signs[ 0 ].signs[ 0 ].name )
|
|
||||||
|
|
||||||
" Here we go. Start Debugging
|
" Here we go. Start Debugging
|
||||||
call feedkeys( "\<F5>", 'xt' )
|
call feedkeys( "\<F5>", 'xt' )
|
||||||
|
|
@ -162,72 +118,130 @@ function! Test_Use_Mappings_HUMAN()
|
||||||
let cur_tabnr = tabpagenr()
|
let cur_tabnr = tabpagenr()
|
||||||
call assert_equal( 5, len( gettabinfo( cur_tabnr )[ 0 ].windows ) )
|
call assert_equal( 5, len( gettabinfo( cur_tabnr )[ 0 ].windows ) )
|
||||||
|
|
||||||
call WaitForAssert( {->
|
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'simple.cpp', 15, 1 )
|
||||||
\ assert_equal( 'simple.cpp', bufname( '%' ), 'Current buffer' )
|
|
||||||
\ }, 10000 )
|
|
||||||
call assert_equal( 15, line( '.' ), 'Current line' )
|
|
||||||
call assert_equal( 1, col( '.' ), 'Current column' )
|
|
||||||
|
|
||||||
let signs = sign_getplaced( '%', {
|
|
||||||
\ 'group': 'VimspectorCode',
|
|
||||||
\ } )
|
|
||||||
|
|
||||||
call assert_equal( 1, len( signs ), 'Sign-buffers' )
|
|
||||||
call assert_equal( 2, len( signs[ 0 ].signs ), 'Signs in buffer' )
|
|
||||||
|
|
||||||
let pc_index = -1
|
|
||||||
let index = 0
|
|
||||||
while index < len( signs[ 0 ].signs )
|
|
||||||
let s = signs[ 0 ].signs[ index ]
|
|
||||||
if s.name ==# 'vimspectorPC'
|
|
||||||
if pc_index >= 0
|
|
||||||
call assert_report( 'Found too many PC signs!' )
|
|
||||||
endif
|
|
||||||
let pc_index = index
|
|
||||||
endif
|
|
||||||
let index = index + 1
|
|
||||||
endwhile
|
|
||||||
call assert_true( pc_index >= 0 )
|
|
||||||
call assert_equal( 15, signs[ 0 ].signs[ pc_index ].lnum )
|
|
||||||
|
|
||||||
" Step
|
" Step
|
||||||
call feedkeys( "\<F10>", 'xt' )
|
call feedkeys( "\<F10>", 'xt' )
|
||||||
|
|
||||||
call WaitForAssert( {-> assert_equal( 16, line( '.' ), 'Current line' ) } )
|
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'simple.cpp', 16, 1 )
|
||||||
call assert_equal( 'simple.cpp', bufname( '%' ), 'Current buffer' )
|
call WaitForAssert( {->
|
||||||
call assert_equal( 1, col( '.' ), 'Current column' )
|
\ vimspector#test#signs#AssertPCIsAtLineInBuffer( 'simple.cp', 16 )
|
||||||
|
\ } )
|
||||||
|
|
||||||
let signs = sign_getplaced( '%', {
|
call vimspector#test#setup#Reset()
|
||||||
\ 'group': 'VimspectorCode',
|
|
||||||
\ } )
|
lcd -
|
||||||
|
%bwipeout!
|
||||||
call assert_equal( 1, len( signs ), 'Sign-buffers' )
|
endfunction
|
||||||
call assert_equal( 2, len( signs[ 0 ].signs ), 'Signs in buffer' )
|
|
||||||
|
function! SetUp_Test_StopAtEntry()
|
||||||
let pc_index = -1
|
let g:vimspector_enable_mappings = 'HUMAN'
|
||||||
let index = 0
|
endfunction
|
||||||
while index < len( signs[ 0 ].signs )
|
|
||||||
let s = signs[ 0 ].signs[ index ]
|
function Test_StopAtEntry()
|
||||||
if s.name ==# 'vimspectorPC'
|
lcd testdata/cpp/simple
|
||||||
if pc_index >= 0
|
edit simple.cpp
|
||||||
call assert_report( 'Found too many PC signs!' )
|
call setpos( '.', [ 0, 1, 1 ] )
|
||||||
endif
|
|
||||||
let pc_index = index
|
" Test stopAtEntry behaviour
|
||||||
endif
|
call feedkeys( "\<F5>", 'xt' )
|
||||||
let index = index + 1
|
|
||||||
endwhile
|
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'simple.cpp', 15, 1 )
|
||||||
call assert_true( pc_index >= 0 )
|
call WaitForAssert( {->
|
||||||
call assert_equal( 16, signs[ 0 ].signs[ pc_index ].lnum )
|
\ vimspector#test#signs#AssertPCIsAtLineInBuffer( 'simple.cpp', 15 )
|
||||||
|
\ } )
|
||||||
call vimspector#Reset()
|
|
||||||
|
call vimspector#test#setup#Reset()
|
||||||
call vimspector#ClearBreakpoints()
|
|
||||||
|
lcd -
|
||||||
let signs = sign_getplaced( '%', {
|
%bwipeout!
|
||||||
\ 'group': 'VimspectorBP'
|
endfunction
|
||||||
\ } )
|
|
||||||
call assert_equal( 1, len( signs ), 1 )
|
function! SetUp_Test_DisableBreakpointWhileDebugging()
|
||||||
call assert_equal( 0, len( signs[ 0 ].signs ) )
|
let g:vimspector_enable_mappings = 'HUMAN'
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function Test_DisableBreakpointWhileDebugging()
|
||||||
|
lcd testdata/cpp/simple
|
||||||
|
edit simple.cpp
|
||||||
|
call setpos( '.', [ 0, 15, 1 ] )
|
||||||
|
|
||||||
|
" Test stopAtEntry behaviour
|
||||||
|
call feedkeys( "\<F5>", 'xt' )
|
||||||
|
|
||||||
|
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'simple.cpp', 15, 1 )
|
||||||
|
call WaitForAssert( {->
|
||||||
|
\ vimspector#test#signs#AssertPCIsAtLineInBuffer( 'simple.cpp', 15 )
|
||||||
|
\ } )
|
||||||
|
call vimspector#test#signs#AssertSignGroupEmpty( 'VimspectorBP' )
|
||||||
|
|
||||||
|
call setpos( '.', [ 0, 16, 1 ] )
|
||||||
|
|
||||||
|
" Add the breakpoint
|
||||||
|
call feedkeys( "\<F9>", 'xt' )
|
||||||
|
call WaitForAssert( {->
|
||||||
|
\ vimspector#test#signs#AssertSignGroupSingletonAtLine(
|
||||||
|
\ 'VimspectorCode',
|
||||||
|
\ 16,
|
||||||
|
\ 'vimspectorBP' )
|
||||||
|
\ } )
|
||||||
|
|
||||||
|
" Remove the breakpoint
|
||||||
|
call feedkeys( "\<F9>", 'xt' )
|
||||||
|
call WaitForAssert( {->
|
||||||
|
\ vimspector#test#signs#AssertSignGroupEmptyAtLine( 'VimspectorCode',
|
||||||
|
\ 16 )
|
||||||
|
\ } )
|
||||||
|
|
||||||
|
" Add the breakpoint
|
||||||
|
call feedkeys( "\<F9>", 'xt' )
|
||||||
|
call WaitForAssert( {->
|
||||||
|
\ vimspector#test#signs#AssertSignGroupSingletonAtLine(
|
||||||
|
\ 'VimspectorCode',
|
||||||
|
\ 16,
|
||||||
|
\ 'vimspectorBP' )
|
||||||
|
\ } )
|
||||||
|
|
||||||
|
" Run to breakpoint
|
||||||
|
call setpos( '.', [ 0, 15, 1 ] )
|
||||||
|
call feedkeys( "\<F5>", 'xt' )
|
||||||
|
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'simple.cpp', 16, 1 )
|
||||||
|
call WaitForAssert( {->
|
||||||
|
\ vimspector#test#signs#AssertPCIsAtLineInBuffer( 'simple.cpp', 16 )
|
||||||
|
\ } )
|
||||||
|
|
||||||
|
call vimspector#Reset()
|
||||||
|
call WaitForAssert( {->
|
||||||
|
\ assert_true ( pyxeval( '_vimspector_session._connection is None' ) )
|
||||||
|
\ } )
|
||||||
|
call WaitForAssert( {->
|
||||||
|
\ assert_true( pyxeval( '_vimspector_session._uiTab is None' ) )
|
||||||
|
\ } )
|
||||||
|
|
||||||
|
" Check breakpoint is now a user breakpoint
|
||||||
|
call setpos( '.', [ bufnr( 'simple.cpp' ), 1, 1 ] )
|
||||||
|
call vimspector#test#signs#AssertSignGroupSingletonAtLine(
|
||||||
|
\ 'VimspectorBP',
|
||||||
|
\ 16,
|
||||||
|
\ 'vimspectorBP' )
|
||||||
|
|
||||||
|
" Disable the breakpoint
|
||||||
|
call setpos( '.', [ bufnr( 'simple.cpp' ), 16, 1 ] )
|
||||||
|
call feedkeys( "\<F9>", 'xt' )
|
||||||
|
call vimspector#test#signs#AssertSignGroupSingletonAtLine(
|
||||||
|
\ 'VimspectorBP',
|
||||||
|
\ 16,
|
||||||
|
\ 'vimspectorBPDisabled' )
|
||||||
|
|
||||||
|
" And delete it
|
||||||
|
call feedkeys( "\<F9>", 'xt' )
|
||||||
|
call vimspector#test#signs#AssertSignGroupEmptyAtLine(
|
||||||
|
\ 'VimspectorBP',
|
||||||
|
\ 16 )
|
||||||
|
|
||||||
|
call vimspector#ClearBreakpoints()
|
||||||
|
call vimspector#test#signs#AssertSignGroupEmpty( 'VimspectorBP' )
|
||||||
|
call vimspector#test#signs#AssertSignGroupEmpty( 'VimspectorCode' )
|
||||||
|
|
||||||
lcd -
|
lcd -
|
||||||
%bwipeout!
|
%bwipeout!
|
||||||
|
|
|
||||||
36
tests/lib/autoload/vimspector/test/setup.vim
Normal file
36
tests/lib/autoload/vimspector/test/setup.vim
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
function! vimspector#test#setup#SetUpWithMappings( mappings ) abort
|
||||||
|
if exists ( 'g:loaded_vimpector' )
|
||||||
|
unlet g:loaded_vimpector
|
||||||
|
endif
|
||||||
|
|
||||||
|
if a:mappings != v:none
|
||||||
|
let g:vimspector_enable_mappings = a:mappings
|
||||||
|
endif
|
||||||
|
|
||||||
|
source vimrc
|
||||||
|
|
||||||
|
" This is a bit of a hack
|
||||||
|
runtime! plugin/**/*.vim
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! vimspector#test#setup#ClearDown() abort
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! vimspector#test#setup#Reset() abort
|
||||||
|
call vimspector#Reset()
|
||||||
|
call WaitForAssert( {->
|
||||||
|
\ assert_true( pyxeval( '_vimspector_session._connection is None' ) )
|
||||||
|
\ } )
|
||||||
|
call WaitForAssert( {->
|
||||||
|
\ assert_true( pyxeval( '_vimspector_session._uiTab is None' ) )
|
||||||
|
\ }, 10000 )
|
||||||
|
|
||||||
|
call vimspector#test#signs#AssertSignGroupEmpty( 'VimspectorCode' )
|
||||||
|
call vimspector#ClearBreakpoints()
|
||||||
|
call vimspector#test#signs#AssertSignGroupEmpty( 'VimspectorBP' )
|
||||||
|
|
||||||
|
if exists( '*vimspector#internal#state#Reset' )
|
||||||
|
call vimspector#internal#state#Reset()
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
93
tests/lib/autoload/vimspector/test/signs.vim
Normal file
93
tests/lib/autoload/vimspector/test/signs.vim
Normal file
|
|
@ -0,0 +1,93 @@
|
||||||
|
function! vimspector#test#signs#AssertCursorIsAtLineInBuffer( buffer,
|
||||||
|
\ line,
|
||||||
|
\ column ) abort
|
||||||
|
call WaitForAssert( {->
|
||||||
|
\ assert_equal( a:buffer, bufname( '%' ), 'Current buffer' )
|
||||||
|
\ }, 10000 )
|
||||||
|
call WaitForAssert( {->
|
||||||
|
\ assert_equal( a:line, line( '.' ), 'Current line' )
|
||||||
|
\ }, 10000 )
|
||||||
|
call assert_equal( a:column, col( '.' ), 'Current column' )
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! vimspector#test#signs#AssertPCIsAtLineInBuffer( buffer, line ) abort
|
||||||
|
let signs = sign_getplaced( a:buffer, {
|
||||||
|
\ 'group': 'VimspectorCode',
|
||||||
|
\ } )
|
||||||
|
|
||||||
|
if assert_equal( 1, len( signs ), 'Number of buffers named ' . a:buffer )
|
||||||
|
return 1
|
||||||
|
endif
|
||||||
|
|
||||||
|
if assert_true( len( signs[ 0 ].signs ) >= 1,
|
||||||
|
\ 'At least one VimspectorCode sign' )
|
||||||
|
return 1
|
||||||
|
endif
|
||||||
|
|
||||||
|
let pc_index = -1
|
||||||
|
let index = 0
|
||||||
|
while index < len( signs[ 0 ].signs )
|
||||||
|
let s = signs[ 0 ].signs[ index ]
|
||||||
|
if s.name ==# 'vimspectorPC'
|
||||||
|
if assert_false( pc_index >= 0, 'Too many PC signs' )
|
||||||
|
return 1
|
||||||
|
endif
|
||||||
|
let pc_index = index
|
||||||
|
endif
|
||||||
|
let index = index + 1
|
||||||
|
endwhile
|
||||||
|
return assert_true( pc_index >= 0 ) ||
|
||||||
|
\ assert_equal( a:line, signs[ 0 ].signs[ pc_index ].lnum )
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! vimspector#test#signs#AssertSignGroupSingletonAtLine( group,
|
||||||
|
\ line,
|
||||||
|
\ sign_name )
|
||||||
|
\ abort
|
||||||
|
|
||||||
|
let signs = sign_getplaced( '%', {
|
||||||
|
\ 'group': a:group,
|
||||||
|
\ 'lnum': a:line,
|
||||||
|
\ } )
|
||||||
|
|
||||||
|
return assert_equal( 1,
|
||||||
|
\ len( signs ),
|
||||||
|
\ 'Num buffers named %' ) ||
|
||||||
|
\ assert_equal( 1,
|
||||||
|
\ len( signs[ 0 ].signs ),
|
||||||
|
\ 'Num signs in ' . a:group . ' at ' . a:line ) ||
|
||||||
|
\ assert_equal( a:sign_name,
|
||||||
|
\ signs[ 0 ].signs[ 0 ].name,
|
||||||
|
\ 'Sign in group ' . a:group . ' at ' . a:line )
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
function! vimspector#test#signs#AssertSignGroupEmptyAtLine( group, line ) abort
|
||||||
|
let signs = sign_getplaced( '%', {
|
||||||
|
\ 'group': a:group,
|
||||||
|
\ 'lnum': line( '.' )
|
||||||
|
\ } )
|
||||||
|
|
||||||
|
return assert_equal( 1,
|
||||||
|
\ len( signs ),
|
||||||
|
\ 'Num buffers named %' ) ||
|
||||||
|
\ assert_equal( 0,
|
||||||
|
\ len( signs[ 0 ].signs ),
|
||||||
|
\ 'Num signs in ' . a:group . ' at ' . a:line )
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
function! vimspector#test#signs#AssertSignGroupEmpty( group ) abort
|
||||||
|
let signs = sign_getplaced( '%', {
|
||||||
|
\ 'group': a:group,
|
||||||
|
\ } )
|
||||||
|
return assert_equal( 1,
|
||||||
|
\ len( signs ),
|
||||||
|
\ 'Num buffers named %' ) ||
|
||||||
|
\ assert_equal( 0,
|
||||||
|
\ len( signs[ 0 ].signs ),
|
||||||
|
\ 'Num signs in ' . a:group )
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -17,8 +17,6 @@ if !has('terminal')
|
||||||
finish
|
finish
|
||||||
endif
|
endif
|
||||||
|
|
||||||
source lib/shared.vim
|
|
||||||
|
|
||||||
" Run Vim with "arguments" in a new terminal window.
|
" Run Vim with "arguments" in a new terminal window.
|
||||||
" By default uses a size of 20 lines and 75 columns.
|
" By default uses a size of 20 lines and 75 columns.
|
||||||
" Returns the buffer number of the terminal.
|
" Returns the buffer number of the terminal.
|
||||||
|
|
@ -126,7 +126,7 @@ endfunc
|
||||||
" When running into the timeout an exception is thrown, thus the function does
|
" When running into the timeout an exception is thrown, thus the function does
|
||||||
" not return.
|
" not return.
|
||||||
func WaitFor(expr, ...)
|
func WaitFor(expr, ...)
|
||||||
let timeout = get(a:000, 0, 5000)
|
let timeout = get(a:000, 0, 10000)
|
||||||
let slept = s:WaitForCommon(a:expr, v:null, timeout)
|
let slept = s:WaitForCommon(a:expr, v:null, timeout)
|
||||||
if slept < 0
|
if slept < 0
|
||||||
throw 'WaitFor() timed out after ' . timeout . ' msec'
|
throw 'WaitFor() timed out after ' . timeout . ' msec'
|
||||||
|
|
@ -134,8 +134,9 @@ func WaitFor(expr, ...)
|
||||||
return slept
|
return slept
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
" Wait for up to five seconds for "assert" to return zero. "assert" must be a
|
" Wait for up to five seconds for "assert" to return without adding to v:errors.
|
||||||
" (lambda) function containing one assert function. Example:
|
" "assert" must be a (lambda) function containing one assert function.
|
||||||
|
" Example:
|
||||||
" call WaitForAssert({-> assert_equal("dead", job_status(job)})
|
" call WaitForAssert({-> assert_equal("dead", job_status(job)})
|
||||||
"
|
"
|
||||||
" A second argument can be used to specify a different timeout in msec.
|
" A second argument can be used to specify a different timeout in msec.
|
||||||
|
|
@ -160,13 +161,15 @@ func s:WaitForCommon(expr, assert, timeout)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
while 1
|
while 1
|
||||||
|
let errors_before = len( v:errors )
|
||||||
if type(a:expr) == v:t_func
|
if type(a:expr) == v:t_func
|
||||||
let success = a:expr()
|
let success = a:expr()
|
||||||
elseif type(a:assert) == v:t_func
|
elseif type(a:assert) == v:t_func
|
||||||
let success = a:assert() == 0
|
let success = a:assert() == 0 && len( v:errors ) == errors_before
|
||||||
else
|
else
|
||||||
let success = eval(a:expr)
|
let success = eval(a:expr)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if success
|
if success
|
||||||
return slept
|
return slept
|
||||||
endif
|
endif
|
||||||
|
|
@ -174,9 +177,10 @@ func s:WaitForCommon(expr, assert, timeout)
|
||||||
if slept >= a:timeout
|
if slept >= a:timeout
|
||||||
break
|
break
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if type(a:assert) == v:t_func
|
if type(a:assert) == v:t_func
|
||||||
" Remove the error added by the assert function.
|
" Remove the errors added by the assert function.
|
||||||
call remove(v:errors, -1)
|
call remove(v:errors, -1 * len( v:errors ) - errors_before )
|
||||||
endif
|
endif
|
||||||
|
|
||||||
sleep 10m
|
sleep 10m
|
||||||
|
|
@ -28,7 +28,7 @@
|
||||||
" When debugging a test it can be useful to add messages to v:errors:
|
" When debugging a test it can be useful to add messages to v:errors:
|
||||||
" call add(v:errors, "this happened")
|
" call add(v:errors, "this happened")
|
||||||
|
|
||||||
set rtp=$VIM/vimfiles,$VIMRUNTIME,$VIM/vimfiles/after
|
set rtp=$PWD/lib,$VIM/vimfiles,$VIMRUNTIME,$VIM/vimfiles/after
|
||||||
if has('packages')
|
if has('packages')
|
||||||
let &packpath = &rtp
|
let &packpath = &rtp
|
||||||
endif
|
endif
|
||||||
|
|
@ -116,6 +116,11 @@ func RunTheTest(test)
|
||||||
try
|
try
|
||||||
let s:test = a:test
|
let s:test = a:test
|
||||||
let s:testid = g:testpath . ':' . a:test
|
let s:testid = g:testpath . ':' . a:test
|
||||||
|
let test_filesafe = substitute( a:test, ')', '_', 'g' )
|
||||||
|
let test_filesafe = substitute( test_filesafe, '(', '_', 'g' )
|
||||||
|
let test_filesafe = substitute( test_filesafe, ',', '_', 'g' )
|
||||||
|
let test_filesafe = substitute( test_filesafe, ':', '_', 'g' )
|
||||||
|
let s:testid_filesafe = g:testpath . '_' . test_filesafe
|
||||||
au VimLeavePre * call EarlyExit(s:test)
|
au VimLeavePre * call EarlyExit(s:test)
|
||||||
exe 'call ' . a:test
|
exe 'call ' . a:test
|
||||||
au! VimLeavePre
|
au! VimLeavePre
|
||||||
|
|
@ -201,6 +206,12 @@ func AfterTheTest()
|
||||||
call add(s:errors, 'Found errors in ' . s:testid . ':')
|
call add(s:errors, 'Found errors in ' . s:testid . ':')
|
||||||
call extend(s:errors, v:errors)
|
call extend(s:errors, v:errors)
|
||||||
let v:errors = []
|
let v:errors = []
|
||||||
|
|
||||||
|
let log = readfile( expand( '~/.vimspector.log' ) )
|
||||||
|
let logfile = s:testid_filesafe . '.vimspector.log'
|
||||||
|
call writefile( log, logfile, 's' )
|
||||||
|
call add( s:messages, 'Wrote log for failed test: ' . logfile )
|
||||||
|
call extend( s:messages, log )
|
||||||
endif
|
endif
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
|
@ -306,51 +317,7 @@ endif
|
||||||
for s:test in sort(s:tests)
|
for s:test in sort(s:tests)
|
||||||
" Silence, please!
|
" Silence, please!
|
||||||
set belloff=all
|
set belloff=all
|
||||||
let prev_error = ''
|
|
||||||
let total_errors = []
|
|
||||||
let run_nr = 1
|
|
||||||
|
|
||||||
call RunTheTest(s:test)
|
call RunTheTest(s:test)
|
||||||
|
|
||||||
" Repeat a flaky test. Give up when:
|
|
||||||
" - it fails again with the same message
|
|
||||||
" - it fails five times (with a different mesage)
|
|
||||||
if len(v:errors) > 0
|
|
||||||
\ && (index(s:flaky_tests, s:test) >= 0
|
|
||||||
\ || v:errors[0] =~ s:flaky_errors_re)
|
|
||||||
while 1
|
|
||||||
call add(s:messages, 'Found errors in ' . s:testid . ':')
|
|
||||||
call extend(s:messages, v:errors)
|
|
||||||
|
|
||||||
call add(total_errors, 'Run ' . run_nr . ':')
|
|
||||||
call extend(total_errors, v:errors)
|
|
||||||
|
|
||||||
if run_nr == 5 || prev_error == v:errors[0]
|
|
||||||
call add(total_errors, 'Flaky test failed too often, giving up')
|
|
||||||
let v:errors = total_errors
|
|
||||||
break
|
|
||||||
endif
|
|
||||||
|
|
||||||
call add(s:messages, 'Flaky test failed, running it again')
|
|
||||||
|
|
||||||
" Flakiness is often caused by the system being very busy. Sleep a
|
|
||||||
" couple of seconds to have a higher chance of succeeding the second
|
|
||||||
" time.
|
|
||||||
sleep 2
|
|
||||||
|
|
||||||
let prev_error = v:errors[0]
|
|
||||||
let v:errors = []
|
|
||||||
let run_nr += 1
|
|
||||||
|
|
||||||
call RunTheTest(s:test)
|
|
||||||
|
|
||||||
if len(v:errors) == 0
|
|
||||||
" Test passed on rerun.
|
|
||||||
break
|
|
||||||
endif
|
|
||||||
endwhile
|
|
||||||
endif
|
|
||||||
|
|
||||||
call AfterTheTest()
|
call AfterTheTest()
|
||||||
endfor
|
endfor
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,9 @@
|
||||||
source lib/shared.vim
|
|
||||||
|
|
||||||
function! SetUp()
|
function! SetUp()
|
||||||
if exists ( 'g:loaded_vimpector' )
|
call vimspector#test#setup#SetUpWithMappings( 'HUMAN' )
|
||||||
unlet g:loaded_vimpector
|
endfunction
|
||||||
endif
|
|
||||||
|
|
||||||
let g:vimspector_enable_mappings = 'HUMAN'
|
function! ClearDown()
|
||||||
source vimrc
|
call vimspector#test#setup#ClearDown()
|
||||||
|
|
||||||
" This is a bit of a hack
|
|
||||||
runtime! plugin/**/*.vim
|
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! Test_Step_With_Different_Tabpage()
|
function! Test_Step_With_Different_Tabpage()
|
||||||
|
|
|
||||||
1
tests/testdata/cpp/simple/.gitignore
vendored
1
tests/testdata/cpp/simple/.gitignore
vendored
|
|
@ -1 +1,2 @@
|
||||||
simple
|
simple
|
||||||
|
variables
|
||||||
|
|
|
||||||
12
tests/testdata/cpp/simple/Makefile
vendored
12
tests/testdata/cpp/simple/Makefile
vendored
|
|
@ -1,7 +1,11 @@
|
||||||
CXXFLAGS=-g -O0
|
CXXFLAGS=-g -O0 -std=c++17
|
||||||
|
|
||||||
simple: simple.cpp
|
.PHONY: all
|
||||||
|
|
||||||
|
TARGETS=simple variables
|
||||||
|
|
||||||
|
all: $(TARGETS)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f simple
|
rm -f $(TARGETS)
|
||||||
rm -rf simple.dSYM
|
rm -rf $(TARGETS:%=%.dSYM)
|
||||||
|
|
|
||||||
11
tests/testdata/cpp/simple/variables.cpp
vendored
Normal file
11
tests/testdata/cpp/simple/variables.cpp
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
std::cout << "Hello world!" << std::endl;
|
||||||
|
int a = 1;
|
||||||
|
++a;
|
||||||
|
int& b = a;
|
||||||
|
++a;
|
||||||
|
std::cout << "a: " << a << " b: " << b << std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue