test_termdebug.vim 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. " Test for the termdebug plugin
  2. source shared.vim
  3. source check.vim
  4. CheckUnix
  5. " CheckFeature terminal
  6. CheckExecutable gdb
  7. CheckExecutable gcc
  8. let g:GDB = exepath('gdb')
  9. if g:GDB->empty()
  10. throw 'Skipped: gdb is not found in $PATH'
  11. endif
  12. let g:GCC = exepath('gcc')
  13. if g:GCC->empty()
  14. throw 'Skipped: gcc is not found in $PATH'
  15. endif
  16. function s:generate_files(bin_name)
  17. let src_name = a:bin_name .. '.c'
  18. let lines =<< trim END
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. int isprime(int n)
  22. {
  23. if (n <= 1)
  24. return 0;
  25. for (int i = 2; i <= n / 2; i++)
  26. if (n % i == 0)
  27. return 0;
  28. return 1;
  29. }
  30. int main(int argc, char *argv[])
  31. {
  32. int n = 7;
  33. printf("%d is %s prime\n", n, isprime(n) ? "a" : "not a");
  34. return 0;
  35. }
  36. END
  37. call writefile(lines, src_name)
  38. call system($'{g:GCC} -g -o {a:bin_name} {src_name}')
  39. endfunction
  40. function s:cleanup_files(bin_name)
  41. call delete(a:bin_name)
  42. call delete(a:bin_name .. '.c')
  43. endfunction
  44. packadd termdebug
  45. func Test_termdebug_basic()
  46. let bin_name = 'XTD_basic'
  47. let src_name = bin_name .. '.c'
  48. call s:generate_files(bin_name)
  49. edit XTD_basic.c
  50. Termdebug ./XTD_basic
  51. call WaitForAssert({-> assert_equal(3, winnr('$'))})
  52. let gdb_buf = winbufnr(1)
  53. wincmd b
  54. Break 9
  55. call Nterm_wait(gdb_buf)
  56. redraw!
  57. call assert_equal([
  58. \ {'lnum': 9, 'id': 1014, 'name': 'debugBreakpoint1.0',
  59. \ 'priority': 110, 'group': 'TermDebug'}],
  60. \ sign_getplaced('', #{group: 'TermDebug'})[0].signs)
  61. Run
  62. call Nterm_wait(gdb_buf, 400)
  63. redraw!
  64. call WaitForAssert({-> assert_equal([
  65. \ {'lnum': 9, 'id': 12, 'name': 'debugPC', 'priority': 110,
  66. \ 'group': 'TermDebug'},
  67. \ {'lnum': 9, 'id': 1014, 'name': 'debugBreakpoint1.0',
  68. \ 'priority': 110, 'group': 'TermDebug'}],
  69. "\ sign_getplaced('', #{group: 'TermDebug'})[0].signs)})
  70. \ sign_getplaced('', #{group: 'TermDebug'})[0].signs->reverse())})
  71. Finish
  72. call Nterm_wait(gdb_buf)
  73. redraw!
  74. call WaitForAssert({-> assert_equal([
  75. \ {'lnum': 9, 'id': 1014, 'name': 'debugBreakpoint1.0',
  76. \ 'priority': 110, 'group': 'TermDebug'},
  77. \ {'lnum': 20, 'id': 12, 'name': 'debugPC',
  78. \ 'priority': 110, 'group': 'TermDebug'}],
  79. \ sign_getplaced('', #{group: 'TermDebug'})[0].signs)})
  80. Continue
  81. call Nterm_wait(gdb_buf)
  82. let i = 2
  83. while i <= 258
  84. Break
  85. call Nterm_wait(gdb_buf)
  86. if i == 2
  87. call WaitForAssert({-> assert_equal(sign_getdefined('debugBreakpoint2.0')[0].text, '02')})
  88. endif
  89. if i == 10
  90. call WaitForAssert({-> assert_equal(sign_getdefined('debugBreakpoint10.0')[0].text, '0A')})
  91. endif
  92. if i == 168
  93. call WaitForAssert({-> assert_equal(sign_getdefined('debugBreakpoint168.0')[0].text, 'A8')})
  94. endif
  95. if i == 255
  96. call WaitForAssert({-> assert_equal(sign_getdefined('debugBreakpoint255.0')[0].text, 'FF')})
  97. endif
  98. if i == 256
  99. call WaitForAssert({-> assert_equal(sign_getdefined('debugBreakpoint256.0')[0].text, 'F+')})
  100. endif
  101. if i == 258
  102. call WaitForAssert({-> assert_equal(sign_getdefined('debugBreakpoint258.0')[0].text, 'F+')})
  103. endif
  104. let i += 1
  105. endwhile
  106. let cn = 0
  107. " 60 is approx spaceBuffer * 3
  108. if winwidth(0) <= 78 + 60
  109. Var
  110. call assert_equal(winnr('$'), winnr())
  111. call assert_equal(['col', [['leaf', 1002], ['leaf', 1001], ['leaf', 1000], ['leaf', 1003 + cn]]], winlayout())
  112. let cn += 1
  113. bw!
  114. Asm
  115. call assert_equal(winnr('$'), winnr())
  116. call assert_equal(['col', [['leaf', 1002], ['leaf', 1001], ['leaf', 1000], ['leaf', 1003 + cn]]], winlayout())
  117. let cn += 1
  118. bw!
  119. endif
  120. set columns=160
  121. call Nterm_wait(gdb_buf)
  122. let winw = winwidth(0)
  123. Var
  124. if winwidth(0) < winw
  125. call assert_equal(winnr('$') - 1, winnr())
  126. call assert_equal(['col', [['leaf', 1002], ['leaf', 1001], ['row', [['leaf', 1003 + cn], ['leaf', 1000]]]]], winlayout())
  127. let cn += 1
  128. bw!
  129. endif
  130. let winw = winwidth(0)
  131. Asm
  132. if winwidth(0) < winw
  133. call assert_equal(winnr('$') - 1, winnr())
  134. call assert_equal(['col', [['leaf', 1002], ['leaf', 1001], ['row', [['leaf', 1003 + cn], ['leaf', 1000]]]]], winlayout())
  135. let cn += 1
  136. bw!
  137. endif
  138. set columns&
  139. call Nterm_wait(gdb_buf)
  140. wincmd t
  141. quit!
  142. redraw!
  143. call WaitForAssert({-> assert_equal(1, winnr('$'))})
  144. call assert_equal([], sign_getplaced('', #{group: 'TermDebug'})[0].signs)
  145. for use_prompt in [0, 1]
  146. let g:termdebug_config = {}
  147. let g:termdebug_config['use_prompt'] = use_prompt
  148. TermdebugCommand ./XTD_basic arg args
  149. call WaitForAssert({-> assert_equal(3, winnr('$'))})
  150. wincmd t
  151. quit!
  152. redraw!
  153. call WaitForAssert({-> assert_equal(1, winnr('$'))})
  154. unlet g:termdebug_config
  155. endfor
  156. call s:cleanup_files(bin_name)
  157. %bw!
  158. endfunc
  159. func Test_termdebug_tbreak()
  160. let g:test_is_flaky = 1
  161. let bin_name = 'XTD_tbreak'
  162. let src_name = bin_name .. '.c'
  163. eval s:generate_files(bin_name)
  164. execute 'edit ' .. src_name
  165. execute 'Termdebug ./' .. bin_name
  166. call WaitForAssert({-> assert_equal(3, winnr('$'))})
  167. let gdb_buf = winbufnr(1)
  168. wincmd b
  169. let bp_line = 22 " 'return' statement in main
  170. let temp_bp_line = 10 " 'if' statement in 'for' loop body
  171. execute "Tbreak " .. temp_bp_line
  172. execute "Break " .. bp_line
  173. call Nterm_wait(gdb_buf)
  174. redraw!
  175. " both temporary and normal breakpoint signs were displayed...
  176. call assert_equal([
  177. \ {'lnum': temp_bp_line, 'id': 1014, 'name': 'debugBreakpoint1.0',
  178. \ 'priority': 110, 'group': 'TermDebug'},
  179. \ {'lnum': bp_line, 'id': 2014, 'name': 'debugBreakpoint2.0',
  180. \ 'priority': 110, 'group': 'TermDebug'}],
  181. \ sign_getplaced('', #{group: 'TermDebug'})[0].signs)
  182. Run
  183. call Nterm_wait(gdb_buf, 400)
  184. redraw!
  185. " debugPC sign is on the line where the temp. bp was set;
  186. " temp. bp sign was removed after hit;
  187. " normal bp sign is still present
  188. call WaitForAssert({-> assert_equal([
  189. \ {'lnum': temp_bp_line, 'id': 12, 'name': 'debugPC', 'priority': 110,
  190. \ 'group': 'TermDebug'},
  191. \ {'lnum': bp_line, 'id': 2014, 'name': 'debugBreakpoint2.0',
  192. \ 'priority': 110, 'group': 'TermDebug'}],
  193. \ sign_getplaced('', #{group: 'TermDebug'})[0].signs)})
  194. Continue
  195. call Nterm_wait(gdb_buf)
  196. redraw!
  197. " debugPC is on the normal breakpoint,
  198. " temp. bp on line 10 was only hit once
  199. call WaitForAssert({-> assert_equal([
  200. \ {'lnum': bp_line, 'id': 12, 'name': 'debugPC', 'priority': 110,
  201. \ 'group': 'TermDebug'},
  202. \ {'lnum': bp_line, 'id': 2014, 'name': 'debugBreakpoint2.0',
  203. \ 'priority': 110, 'group': 'TermDebug'}],
  204. "\ sign_getplaced('', #{group: 'TermDebug'})[0].signs)})
  205. \ sign_getplaced('', #{group: 'TermDebug'})[0].signs->reverse())})
  206. wincmd t
  207. quit!
  208. redraw!
  209. call WaitForAssert({-> assert_equal(1, winnr('$'))})
  210. call assert_equal([], sign_getplaced('', #{group: 'TermDebug'})[0].signs)
  211. eval s:cleanup_files(bin_name)
  212. %bw!
  213. endfunc
  214. func Test_termdebug_mapping()
  215. %bw!
  216. call assert_true(maparg('K', 'n', 0, 1)->empty())
  217. call assert_true(maparg('-', 'n', 0, 1)->empty())
  218. call assert_true(maparg('+', 'n', 0, 1)->empty())
  219. Termdebug
  220. call WaitForAssert({-> assert_equal(3, winnr('$'))})
  221. wincmd b
  222. call assert_false(maparg('K', 'n', 0, 1)->empty())
  223. call assert_false(maparg('-', 'n', 0, 1)->empty())
  224. call assert_false(maparg('+', 'n', 0, 1)->empty())
  225. call assert_false(maparg('K', 'n', 0, 1).buffer)
  226. call assert_false(maparg('-', 'n', 0, 1).buffer)
  227. call assert_false(maparg('+', 'n', 0, 1).buffer)
  228. call assert_equal(':Evaluate<CR>', maparg('K', 'n', 0, 1).rhs)
  229. wincmd t
  230. quit!
  231. redraw!
  232. call WaitForAssert({-> assert_equal(1, winnr('$'))})
  233. call assert_true(maparg('K', 'n', 0, 1)->empty())
  234. call assert_true(maparg('-', 'n', 0, 1)->empty())
  235. call assert_true(maparg('+', 'n', 0, 1)->empty())
  236. %bw!
  237. nnoremap K :echom "K"<cr>
  238. nnoremap - :echom "-"<cr>
  239. nnoremap + :echom "+"<cr>
  240. Termdebug
  241. call WaitForAssert({-> assert_equal(3, winnr('$'))})
  242. wincmd b
  243. call assert_false(maparg('K', 'n', 0, 1)->empty())
  244. call assert_false(maparg('-', 'n', 0, 1)->empty())
  245. call assert_false(maparg('+', 'n', 0, 1)->empty())
  246. call assert_false(maparg('K', 'n', 0, 1).buffer)
  247. call assert_false(maparg('-', 'n', 0, 1).buffer)
  248. call assert_false(maparg('+', 'n', 0, 1).buffer)
  249. call assert_equal(':Evaluate<CR>', maparg('K', 'n', 0, 1).rhs)
  250. wincmd t
  251. quit!
  252. redraw!
  253. call WaitForAssert({-> assert_equal(1, winnr('$'))})
  254. call assert_false(maparg('K', 'n', 0, 1)->empty())
  255. call assert_false(maparg('-', 'n', 0, 1)->empty())
  256. call assert_false(maparg('+', 'n', 0, 1)->empty())
  257. call assert_false(maparg('K', 'n', 0, 1).buffer)
  258. call assert_false(maparg('-', 'n', 0, 1).buffer)
  259. call assert_false(maparg('+', 'n', 0, 1).buffer)
  260. call assert_equal(':echom "K"<cr>', maparg('K', 'n', 0, 1).rhs)
  261. %bw!
  262. " -- Test that local-buffer mappings are restored in the correct buffers --
  263. " local mappings for foo
  264. file foo
  265. nnoremap <buffer> K :echom "bK"<cr>
  266. nnoremap <buffer> - :echom "b-"<cr>
  267. nnoremap <buffer> + :echom "b+"<cr>
  268. " no mappings for 'bar'
  269. enew
  270. file bar
  271. " Start termdebug from foo
  272. buffer foo
  273. Termdebug
  274. call WaitForAssert({-> assert_equal(3, winnr('$'))})
  275. wincmd b
  276. call assert_true(maparg('K', 'n', 0, 1).buffer)
  277. call assert_true(maparg('-', 'n', 0, 1).buffer)
  278. call assert_true(maparg('+', 'n', 0, 1).buffer)
  279. call assert_equal(maparg('K', 'n', 0, 1).rhs, ':echom "bK"<cr>')
  280. Source
  281. buffer bar
  282. call assert_false(maparg('K', 'n', 0, 1)->empty())
  283. call assert_false(maparg('-', 'n', 0, 1)->empty())
  284. call assert_false(maparg('+', 'n', 0, 1)->empty())
  285. call assert_true(maparg('K', 'n', 0, 1).buffer->empty())
  286. call assert_true(maparg('-', 'n', 0, 1).buffer->empty())
  287. call assert_true(maparg('+', 'n', 0, 1).buffer->empty())
  288. wincmd t
  289. quit!
  290. redraw!
  291. call WaitForAssert({-> assert_equal(1, winnr('$'))})
  292. " Termdebug session ended. Buffer 'bar' shall have no mappings
  293. call assert_true(bufname() ==# 'bar')
  294. call assert_false(maparg('K', 'n', 0, 1)->empty())
  295. call assert_false(maparg('-', 'n', 0, 1)->empty())
  296. call assert_false(maparg('+', 'n', 0, 1)->empty())
  297. call assert_true(maparg('K', 'n', 0, 1).buffer->empty())
  298. call assert_true(maparg('-', 'n', 0, 1).buffer->empty())
  299. call assert_true(maparg('+', 'n', 0, 1).buffer->empty())
  300. " Buffer 'foo' shall have the same mapping as before running the termdebug
  301. " session
  302. buffer foo
  303. call assert_true(bufname() ==# 'foo')
  304. call assert_true(maparg('K', 'n', 0, 1).buffer)
  305. call assert_true(maparg('-', 'n', 0, 1).buffer)
  306. call assert_true(maparg('+', 'n', 0, 1).buffer)
  307. call assert_equal(':echom "bK"<cr>', maparg('K', 'n', 0, 1).rhs)
  308. nunmap K
  309. nunmap +
  310. nunmap -
  311. %bw!
  312. endfunc
  313. func Test_termdebug_bufnames()
  314. " Test if user has filename/folders named gdb, Termdebug-gdb-console,
  315. " etc. in the current directory
  316. let g:termdebug_config = {}
  317. let g:termdebug_config['use_prompt'] = 1
  318. let filename = 'gdb'
  319. let replacement_filename = 'Termdebug-gdb-console'
  320. call writefile(['This', 'is', 'a', 'test'], filename, 'D')
  321. " Throw away the file once the test has done.
  322. Termdebug
  323. " Once termdebug has completed the startup you should have 3 windows on screen
  324. call WaitForAssert({-> assert_equal(3, winnr('$'))})
  325. " A file named filename already exists in the working directory,
  326. " hence you must call the newly created buffer differently
  327. call WaitForAssert({-> assert_false(bufexists(filename))})
  328. call WaitForAssert({-> assert_true(bufexists(replacement_filename))})
  329. quit!
  330. call WaitForAssert({-> assert_equal(1, winnr('$'))})
  331. " Check if error message is in :message
  332. let g:termdebug_config['disasm_window'] = 1
  333. let filename = 'Termdebug-asm-listing'
  334. call writefile(['This', 'is', 'a', 'test'], filename, 'D')
  335. " Check only the head of the error message
  336. let error_message = "You have a file/folder named '" .. filename .. "'"
  337. Termdebug
  338. " Once termdebug has completed the startup you should have 4 windows on screen
  339. call WaitForAssert({-> assert_equal(4, winnr('$'))})
  340. call WaitForAssert({-> assert_notequal(-1, stridx(execute('messages'), error_message))})
  341. quit!
  342. wincmd b
  343. wincmd q
  344. call WaitForAssert({-> assert_equal(1, winnr('$'))})
  345. unlet g:termdebug_config
  346. endfunc
  347. function Test_termdebug_save_restore_variables()
  348. " saved mousemodel
  349. let &mousemodel=''
  350. " saved keys
  351. nnoremap K :echo "hello world!"<cr>
  352. let expected_map_K = maparg('K', 'n', 0 , 1)
  353. nnoremap + :echo "hello plus!"<cr>
  354. let expected_map_plus = maparg('+', 'n', 0 , 1)
  355. let expected_map_minus = {}
  356. " saved &columns
  357. let expected_columns = &columns
  358. " We want termdebug to overwrite 'K' map but not '+' map.
  359. let g:termdebug_config = {}
  360. let g:termdebug_config['map_K'] = 1
  361. Termdebug
  362. call WaitForAssert({-> assert_equal(3, winnr('$'))})
  363. call WaitForAssert({-> assert_match(&mousemodel, 'popup_setpos')})
  364. wincmd t
  365. quit!
  366. call WaitForAssert({-> assert_equal(1, winnr('$'))})
  367. call assert_true(empty(&mousemodel))
  368. call assert_true(empty(expected_map_minus))
  369. call assert_equal(expected_map_K.rhs, maparg('K', 'n', 0, 1).rhs)
  370. call assert_equal(expected_map_plus.rhs, maparg('+', 'n', 0, 1).rhs)
  371. call assert_equal(expected_columns, &columns)
  372. nunmap K
  373. nunmap +
  374. unlet g:termdebug_config
  375. endfunction
  376. " vim: shiftwidth=2 sts=2 expandtab