neovim/test/old/testdir/test_termdebug.vim
Yinzuo Jiang 29e05cfb7e
vim-patch:partial:9.1.0482: termdebug plugin needs more love (#29329)
Problem:  termdebug plugin needs more love
Solution: start with some more Vim9 refactoring
          to improve maintenance and readability
          (Ubaldo Tiberi)

List of Changes and the Reasoning Behind Them:

1) Introduction of InitScriptVariables() Function:

Reasoning: This function has been introduced to ensure that when you open and
close Termdebug, and then open it again, there are no leftover script variable
values from the previous session. Leftover values could potentially cause
issues. The goal is for each Termdebug session to be independent of previous
sessions. At startup, all script variables are initialized. The only exception
is g:termdebug_loaded located at the very beginning of the script to prevent
sourcing the script twice. The variables are declared at script level and
defined in InitScriptVariables().

2) More Descriptive Variable Names:

Reasoning: The names of variables have been made more comprehensive. Almost
every Termdebug buffer now has a variable to indicate its name and another
variable to indicate its number, improving code readability and
maintainability. Due to the latest discussion around the &mousemodel option
save/restore mechanism, perhaps some other variables shall be prepended with
saved_.

3) Consistent Naming for GDB Terminal Buffers:

Reasoning: The name of the GDB terminal buffer now matches the name of the GDB
program being used, e.g., 'gdb', 'mygdb', 'arm-eabi-none-gdb', etc. This
ensures clarity and consistency in identifying buffers.

4) Other minor improvements:
Moved EchoErr() on top, added another test, some refactoring, mainly changed
several 0 and 1 to true and false

closes: vim/vim#14980

ef8eab86e2

Co-authored-by: Ubaldo Tiberi <ubaldo.tiberi@volvo.com>
2024-06-14 16:37:38 +08:00

356 lines
11 KiB
VimL

" Test for the termdebug plugin
source shared.vim
source check.vim
CheckUnix
" CheckFeature terminal
CheckExecutable gdb
CheckExecutable gcc
let g:GDB = exepath('gdb')
if g:GDB->empty()
throw 'Skipped: gdb is not found in $PATH'
endif
let g:GCC = exepath('gcc')
if g:GCC->empty()
throw 'Skipped: gcc is not found in $PATH'
endif
function s:generate_files(bin_name)
let src_name = a:bin_name .. '.c'
let lines =<< trim END
#include <stdio.h>
#include <stdlib.h>
int isprime(int n)
{
if (n <= 1)
return 0;
for (int i = 2; i <= n / 2; i++)
if (n % i == 0)
return 0;
return 1;
}
int main(int argc, char *argv[])
{
int n = 7;
printf("%d is %s prime\n", n, isprime(n) ? "a" : "not a");
return 0;
}
END
call writefile(lines, src_name)
call system($'{g:GCC} -g -o {a:bin_name} {src_name}')
endfunction
function s:cleanup_files(bin_name)
call delete(a:bin_name)
call delete(a:bin_name .. '.c')
endfunction
packadd termdebug
func Test_termdebug_basic()
let bin_name = 'XTD_basic'
let src_name = bin_name .. '.c'
call s:generate_files(bin_name)
edit XTD_basic.c
Termdebug ./XTD_basic
call WaitForAssert({-> assert_equal(3, winnr('$'))})
let gdb_buf = winbufnr(1)
wincmd b
Break 9
call Nterm_wait(gdb_buf)
redraw!
call assert_equal([
\ {'lnum': 9, 'id': 1014, 'name': 'debugBreakpoint1.0',
\ 'priority': 110, 'group': 'TermDebug'}],
\ sign_getplaced('', #{group: 'TermDebug'})[0].signs)
Run
call Nterm_wait(gdb_buf, 400)
redraw!
call WaitForAssert({-> assert_equal([
\ {'lnum': 9, 'id': 12, 'name': 'debugPC', 'priority': 110,
\ 'group': 'TermDebug'},
\ {'lnum': 9, 'id': 1014, 'name': 'debugBreakpoint1.0',
\ 'priority': 110, 'group': 'TermDebug'}],
"\ sign_getplaced('', #{group: 'TermDebug'})[0].signs)})
\ sign_getplaced('', #{group: 'TermDebug'})[0].signs->reverse())})
Finish
call Nterm_wait(gdb_buf)
redraw!
call WaitForAssert({-> assert_equal([
\ {'lnum': 9, 'id': 1014, 'name': 'debugBreakpoint1.0',
\ 'priority': 110, 'group': 'TermDebug'},
\ {'lnum': 20, 'id': 12, 'name': 'debugPC',
\ 'priority': 110, 'group': 'TermDebug'}],
\ sign_getplaced('', #{group: 'TermDebug'})[0].signs)})
Continue
call Nterm_wait(gdb_buf)
let i = 2
while i <= 258
Break
call Nterm_wait(gdb_buf)
if i == 2
call WaitForAssert({-> assert_equal(sign_getdefined('debugBreakpoint2.0')[0].text, '02')})
endif
if i == 10
call WaitForAssert({-> assert_equal(sign_getdefined('debugBreakpoint10.0')[0].text, '0A')})
endif
if i == 168
call WaitForAssert({-> assert_equal(sign_getdefined('debugBreakpoint168.0')[0].text, 'A8')})
endif
if i == 255
call WaitForAssert({-> assert_equal(sign_getdefined('debugBreakpoint255.0')[0].text, 'FF')})
endif
if i == 256
call WaitForAssert({-> assert_equal(sign_getdefined('debugBreakpoint256.0')[0].text, 'F+')})
endif
if i == 258
call WaitForAssert({-> assert_equal(sign_getdefined('debugBreakpoint258.0')[0].text, 'F+')})
endif
let i += 1
endwhile
let cn = 0
" 60 is approx spaceBuffer * 3
if winwidth(0) <= 78 + 60
Var
call assert_equal(winnr(), winnr('$'))
call assert_equal(winlayout(), ['col', [['leaf', 1002], ['leaf', 1001], ['leaf', 1000], ['leaf', 1003 + cn]]])
let cn += 1
bw!
Asm
call assert_equal(winnr(), winnr('$'))
call assert_equal(winlayout(), ['col', [['leaf', 1002], ['leaf', 1001], ['leaf', 1000], ['leaf', 1003 + cn]]])
let cn += 1
bw!
endif
set columns=160
call Nterm_wait(gdb_buf)
let winw = winwidth(0)
Var
if winwidth(0) < winw
call assert_equal(winnr(), winnr('$') - 1)
call assert_equal(winlayout(), ['col', [['leaf', 1002], ['leaf', 1001], ['row', [['leaf', 1003 + cn], ['leaf', 1000]]]]])
let cn += 1
bw!
endif
let winw = winwidth(0)
Asm
if winwidth(0) < winw
call assert_equal(winnr(), winnr('$') - 1)
call assert_equal(winlayout(), ['col', [['leaf', 1002], ['leaf', 1001], ['row', [['leaf', 1003 + cn], ['leaf', 1000]]]]])
let cn += 1
bw!
endif
set columns&
call Nterm_wait(gdb_buf)
wincmd t
quit!
redraw!
call WaitForAssert({-> assert_equal(1, winnr('$'))})
call assert_equal([], sign_getplaced('', #{group: 'TermDebug'})[0].signs)
call s:cleanup_files(bin_name)
%bw!
endfunc
func Test_termdebug_tbreak()
let g:test_is_flaky = 1
let bin_name = 'XTD_tbreak'
let src_name = bin_name .. '.c'
eval s:generate_files(bin_name)
execute 'edit ' .. src_name
execute 'Termdebug ./' .. bin_name
call WaitForAssert({-> assert_equal(3, winnr('$'))})
let gdb_buf = winbufnr(1)
wincmd b
let bp_line = 22 " 'return' statement in main
let temp_bp_line = 10 " 'if' statement in 'for' loop body
execute "Tbreak " .. temp_bp_line
execute "Break " .. bp_line
call Nterm_wait(gdb_buf)
redraw!
" both temporary and normal breakpoint signs were displayed...
call assert_equal([
\ {'lnum': temp_bp_line, 'id': 1014, 'name': 'debugBreakpoint1.0',
\ 'priority': 110, 'group': 'TermDebug'},
\ {'lnum': bp_line, 'id': 2014, 'name': 'debugBreakpoint2.0',
\ 'priority': 110, 'group': 'TermDebug'}],
\ sign_getplaced('', #{group: 'TermDebug'})[0].signs)
Run
call Nterm_wait(gdb_buf, 400)
redraw!
" debugPC sign is on the line where the temp. bp was set;
" temp. bp sign was removed after hit;
" normal bp sign is still present
call WaitForAssert({-> assert_equal([
\ {'lnum': temp_bp_line, 'id': 12, 'name': 'debugPC', 'priority': 110,
\ 'group': 'TermDebug'},
\ {'lnum': bp_line, 'id': 2014, 'name': 'debugBreakpoint2.0',
\ 'priority': 110, 'group': 'TermDebug'}],
\ sign_getplaced('', #{group: 'TermDebug'})[0].signs)})
Continue
call Nterm_wait(gdb_buf)
redraw!
" debugPC is on the normal breakpoint,
" temp. bp on line 10 was only hit once
call WaitForAssert({-> assert_equal([
\ {'lnum': bp_line, 'id': 12, 'name': 'debugPC', 'priority': 110,
\ 'group': 'TermDebug'},
\ {'lnum': bp_line, 'id': 2014, 'name': 'debugBreakpoint2.0',
\ 'priority': 110, 'group': 'TermDebug'}],
"\ sign_getplaced('', #{group: 'TermDebug'})[0].signs)})
\ sign_getplaced('', #{group: 'TermDebug'})[0].signs->reverse())})
wincmd t
quit!
redraw!
call WaitForAssert({-> assert_equal(1, winnr('$'))})
call assert_equal([], sign_getplaced('', #{group: 'TermDebug'})[0].signs)
eval s:cleanup_files(bin_name)
%bw!
endfunc
func Test_termdebug_mapping()
%bw!
call assert_true(maparg('K', 'n', 0, 1)->empty())
call assert_true(maparg('-', 'n', 0, 1)->empty())
call assert_true(maparg('+', 'n', 0, 1)->empty())
Termdebug
call WaitForAssert({-> assert_equal(3, winnr('$'))})
wincmd b
call assert_false(maparg('K', 'n', 0, 1)->empty())
call assert_false(maparg('-', 'n', 0, 1)->empty())
call assert_false(maparg('+', 'n', 0, 1)->empty())
call assert_false(maparg('K', 'n', 0, 1).buffer)
call assert_false(maparg('-', 'n', 0, 1).buffer)
call assert_false(maparg('+', 'n', 0, 1).buffer)
call assert_equal(':Evaluate<CR>', maparg('K', 'n', 0, 1).rhs)
wincmd t
quit!
redraw!
call WaitForAssert({-> assert_equal(1, winnr('$'))})
call assert_true(maparg('K', 'n', 0, 1)->empty())
call assert_true(maparg('-', 'n', 0, 1)->empty())
call assert_true(maparg('+', 'n', 0, 1)->empty())
%bw!
nnoremap K :echom "K"<cr>
nnoremap - :echom "-"<cr>
nnoremap + :echom "+"<cr>
Termdebug
call WaitForAssert({-> assert_equal(3, winnr('$'))})
wincmd b
call assert_false(maparg('K', 'n', 0, 1)->empty())
call assert_false(maparg('-', 'n', 0, 1)->empty())
call assert_false(maparg('+', 'n', 0, 1)->empty())
call assert_false(maparg('K', 'n', 0, 1).buffer)
call assert_false(maparg('-', 'n', 0, 1).buffer)
call assert_false(maparg('+', 'n', 0, 1).buffer)
call assert_equal(':Evaluate<CR>', maparg('K', 'n', 0, 1).rhs)
wincmd t
quit!
redraw!
call WaitForAssert({-> assert_equal(1, winnr('$'))})
call assert_false(maparg('K', 'n', 0, 1)->empty())
call assert_false(maparg('-', 'n', 0, 1)->empty())
call assert_false(maparg('+', 'n', 0, 1)->empty())
call assert_false(maparg('K', 'n', 0, 1).buffer)
call assert_false(maparg('-', 'n', 0, 1).buffer)
call assert_false(maparg('+', 'n', 0, 1).buffer)
call assert_equal(':echom "K"<cr>', maparg('K', 'n', 0, 1).rhs)
%bw!
nnoremap <buffer> K :echom "bK"<cr>
nnoremap <buffer> - :echom "b-"<cr>
nnoremap <buffer> + :echom "b+"<cr>
Termdebug
call WaitForAssert({-> assert_equal(3, winnr('$'))})
wincmd b
call assert_true(maparg('K', 'n', 0, 1).buffer)
call assert_true(maparg('-', 'n', 0, 1).buffer)
call assert_true(maparg('+', 'n', 0, 1).buffer)
call assert_equal(maparg('K', 'n', 0, 1).rhs, ':echom "bK"<cr>')
wincmd t
quit!
redraw!
call WaitForAssert({-> assert_equal(1, winnr('$'))})
call assert_true(maparg('K', 'n', 0, 1).buffer)
call assert_true(maparg('-', 'n', 0, 1).buffer)
call assert_true(maparg('+', 'n', 0, 1).buffer)
call assert_equal(':echom "bK"<cr>', maparg('K', 'n', 0, 1).rhs)
%bw!
endfunc
func Test_termdebug_bufnames()
" Test if user has filename/folders named gdb, Termdebug-gdb-console,
" etc. in the current directory
let g:termdebug_config = {}
let g:termdebug_config['use_prompt'] = 1
let filename = 'gdb'
let replacement_filename = 'Termdebug-gdb-console'
call writefile(['This', 'is', 'a', 'test'], filename, 'D')
" Throw away the file once the test has done.
Termdebug
" Once termdebug has completed the startup you should have 3 windows on screen
call WaitForAssert({-> assert_equal(3, winnr('$'))})
" A file named filename already exists in the working directory,
" hence you must call the newly created buffer differently
call WaitForAssert({-> assert_false(bufexists(filename))})
call WaitForAssert({-> assert_true(bufexists(replacement_filename))})
quit!
call WaitForAssert({-> assert_equal(1, winnr('$'))})
" Check if error message is in :message
let g:termdebug_config['disasm_window'] = 1
let filename = 'Termdebug-asm-listing'
call writefile(['This', 'is', 'a', 'test'], filename, 'D')
" Check only the head of the error message
let error_message = "You have a file/folder named '" .. filename .. "'"
Termdebug
" Once termdebug has completed the startup you should have 4 windows on screen
call WaitForAssert({-> assert_equal(4, winnr('$'))})
call WaitForAssert({-> assert_notequal(-1, stridx(execute('messages'), error_message))})
quit!
wincmd b
wincmd q
call WaitForAssert({-> assert_equal(1, winnr('$'))})
unlet g:termdebug_config
endfunc
function Test_termdebug_save_restore_variables()
let &mousemodel=''
Termdebug
call WaitForAssert({-> assert_equal(3, winnr('$'))})
call WaitForAssert({-> assert_match(&mousemodel, 'popup_setpos')})
wincmd t
quit!
call WaitForAssert({-> assert_equal(1, winnr('$'))})
call WaitForAssert({-> assert_true(empty(&mousemodel))})
endfunction
" vim: shiftwidth=2 sts=2 expandtab