1" Test for the quickfix feature.
2
3source check.vim
4CheckFeature quickfix
5
6source screendump.vim
7
8set encoding=utf-8
9
10func s:setup_commands(cchar)
11  if a:cchar == 'c'
12    command! -nargs=* -bang Xlist <mods>clist<bang> <args>
13    command! -nargs=* Xgetexpr <mods>cgetexpr <args>
14    command! -nargs=* Xaddexpr <mods>caddexpr <args>
15    command! -nargs=* -count Xolder <mods><count>colder <args>
16    command! -nargs=* Xnewer <mods>cnewer <args>
17    command! -nargs=* Xopen <mods> copen <args>
18    command! -nargs=* Xwindow <mods>cwindow <args>
19    command! -nargs=* Xbottom <mods>cbottom <args>
20    command! -nargs=* Xclose <mods>cclose <args>
21    command! -nargs=* -bang Xfile <mods>cfile<bang> <args>
22    command! -nargs=* Xgetfile <mods>cgetfile <args>
23    command! -nargs=* Xaddfile <mods>caddfile <args>
24    command! -nargs=* -bang Xbuffer <mods>cbuffer<bang> <args>
25    command! -nargs=* Xgetbuffer <mods>cgetbuffer <args>
26    command! -nargs=* Xaddbuffer <mods>caddbuffer <args>
27    command! -nargs=* Xrewind <mods>crewind <args>
28    command! -count -nargs=* -bang Xnext <mods><count>cnext<bang> <args>
29    command! -count -nargs=* -bang Xprev <mods><count>cprev<bang> <args>
30    command! -nargs=* -bang Xfirst <mods>cfirst<bang> <args>
31    command! -nargs=* -bang Xlast <mods>clast<bang> <args>
32    command! -count -nargs=* -bang Xnfile <mods><count>cnfile<bang> <args>
33    command! -nargs=* -bang Xpfile <mods>cpfile<bang> <args>
34    command! -nargs=* Xexpr <mods>cexpr <args>
35    command! -count -nargs=* Xvimgrep <mods> <count>vimgrep <args>
36    command! -nargs=* Xvimgrepadd <mods> vimgrepadd <args>
37    command! -nargs=* Xgrep <mods> grep <args>
38    command! -nargs=* Xgrepadd <mods> grepadd <args>
39    command! -nargs=* Xhelpgrep helpgrep <args>
40    command! -nargs=0 -count Xcc <count>cc
41    command! -count=1 -nargs=0 Xbelow <mods><count>cbelow
42    command! -count=1 -nargs=0 Xabove <mods><count>cabove
43    command! -count=1 -nargs=0 Xbefore <mods><count>cbefore
44    command! -count=1 -nargs=0 Xafter <mods><count>cafter
45    let g:Xgetlist = function('getqflist')
46    let g:Xsetlist = function('setqflist')
47    call setqflist([], 'f')
48  else
49    command! -nargs=* -bang Xlist <mods>llist<bang> <args>
50    command! -nargs=* Xgetexpr <mods>lgetexpr <args>
51    command! -nargs=* Xaddexpr <mods>laddexpr <args>
52    command! -nargs=* -count Xolder <mods><count>lolder <args>
53    command! -nargs=* Xnewer <mods>lnewer <args>
54    command! -nargs=* Xopen <mods> lopen <args>
55    command! -nargs=* Xwindow <mods>lwindow <args>
56    command! -nargs=* Xbottom <mods>lbottom <args>
57    command! -nargs=* Xclose <mods>lclose <args>
58    command! -nargs=* -bang Xfile <mods>lfile<bang> <args>
59    command! -nargs=* Xgetfile <mods>lgetfile <args>
60    command! -nargs=* Xaddfile <mods>laddfile <args>
61    command! -nargs=* -bang Xbuffer <mods>lbuffer<bang> <args>
62    command! -nargs=* Xgetbuffer <mods>lgetbuffer <args>
63    command! -nargs=* Xaddbuffer <mods>laddbuffer <args>
64    command! -nargs=* Xrewind <mods>lrewind <args>
65    command! -count -nargs=* -bang Xnext <mods><count>lnext<bang> <args>
66    command! -count -nargs=* -bang Xprev <mods><count>lprev<bang> <args>
67    command! -nargs=* -bang Xfirst <mods>lfirst<bang> <args>
68    command! -nargs=* -bang Xlast <mods>llast<bang> <args>
69    command! -count -nargs=* -bang Xnfile <mods><count>lnfile<bang> <args>
70    command! -nargs=* -bang Xpfile <mods>lpfile<bang> <args>
71    command! -nargs=* Xexpr <mods>lexpr <args>
72    command! -count -nargs=* Xvimgrep <mods> <count>lvimgrep <args>
73    command! -nargs=* Xvimgrepadd <mods> lvimgrepadd <args>
74    command! -nargs=* Xgrep <mods> lgrep <args>
75    command! -nargs=* Xgrepadd <mods> lgrepadd <args>
76    command! -nargs=* Xhelpgrep lhelpgrep <args>
77    command! -nargs=0 -count Xcc <count>ll
78    command! -count=1 -nargs=0 Xbelow <mods><count>lbelow
79    command! -count=1 -nargs=0 Xabove <mods><count>labove
80    command! -count=1 -nargs=0 Xbefore <mods><count>lbefore
81    command! -count=1 -nargs=0 Xafter <mods><count>lafter
82    let g:Xgetlist = function('getloclist', [0])
83    let g:Xsetlist = function('setloclist', [0])
84    call setloclist(0, [], 'f')
85  endif
86endfunc
87
88" Tests for the :clist and :llist commands
89func XlistTests(cchar)
90  call s:setup_commands(a:cchar)
91
92  if a:cchar == 'l'
93      call assert_fails('llist', 'E776:')
94  endif
95  " With an empty list, command should return error
96  Xgetexpr []
97  silent! Xlist
98  call assert_true(v:errmsg ==# 'E42: No Errors')
99
100  " Populate the list and then try
101  Xgetexpr ['non-error 1', 'Xtestfile1:1:3:Line1',
102		  \ 'non-error 2', 'Xtestfile2:2:2:Line2',
103		  \ 'non-error| 3', 'Xtestfile3:3:1:Line3']
104
105  " List only valid entries
106  let l = split(execute('Xlist', ''), "\n")
107  call assert_equal([' 2 Xtestfile1:1 col 3: Line1',
108		   \ ' 4 Xtestfile2:2 col 2: Line2',
109		   \ ' 6 Xtestfile3:3 col 1: Line3'], l)
110
111  " List all the entries
112  let l = split(execute('Xlist!', ''), "\n")
113  call assert_equal([' 1: non-error 1', ' 2 Xtestfile1:1 col 3: Line1',
114		   \ ' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2',
115		   \ ' 5: non-error| 3', ' 6 Xtestfile3:3 col 1: Line3'], l)
116
117  " List a range of errors
118  let l = split(execute('Xlist 3,6', ''), "\n")
119  call assert_equal([' 4 Xtestfile2:2 col 2: Line2',
120		   \ ' 6 Xtestfile3:3 col 1: Line3'], l)
121
122  let l = split(execute('Xlist! 3,4', ''), "\n")
123  call assert_equal([' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2'], l)
124
125  let l = split(execute('Xlist -6,-4', ''), "\n")
126  call assert_equal([' 2 Xtestfile1:1 col 3: Line1'], l)
127
128  let l = split(execute('Xlist! -5,-3', ''), "\n")
129  call assert_equal([' 2 Xtestfile1:1 col 3: Line1',
130		   \ ' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2'], l)
131
132  " Test for '+'
133  let l = split(execute('Xlist! +2', ''), "\n")
134  call assert_equal([' 2 Xtestfile1:1 col 3: Line1',
135		   \ ' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2'], l)
136
137  " Different types of errors
138  call g:Xsetlist([{'lnum':10,'col':5,'type':'W', 'text':'Warning','nr':11},
139	      \ {'lnum':20,'col':10,'type':'e','text':'Error','nr':22},
140	      \ {'lnum':30,'col':15,'type':'i','text':'Info','nr':33},
141	      \ {'lnum':40,'col':20,'type':'x', 'text':'Other','nr':44},
142	      \ {'lnum':50,'col':25,'type':"\<C-A>",'text':'one','nr':55}])
143  let l = split(execute('Xlist', ""), "\n")
144  call assert_equal([' 1:10 col 5 warning  11: Warning',
145	      \ ' 2:20 col 10 error  22: Error',
146	      \ ' 3:30 col 15 info  33: Info',
147	      \ ' 4:40 col 20 x  44: Other',
148	      \ ' 5:50 col 25  55: one'], l)
149
150  " Test for module names, one needs to explicitly set `'valid':v:true` so
151  call g:Xsetlist([
152	\ {'lnum':10,'col':5,'type':'W','module':'Data.Text','text':'ModuleWarning','nr':11,'valid':v:true},
153	\ {'lnum':20,'col':10,'type':'W','module':'Data.Text','filename':'Data/Text.hs','text':'ModuleWarning','nr':22,'valid':v:true},
154	\ {'lnum':30,'col':15,'type':'W','filename':'Data/Text.hs','text':'FileWarning','nr':33,'valid':v:true}])
155  let l = split(execute('Xlist', ""), "\n")
156  call assert_equal([' 1 Data.Text:10 col 5 warning  11: ModuleWarning',
157	\ ' 2 Data.Text:20 col 10 warning  22: ModuleWarning',
158	\ ' 3 Data/Text.hs:30 col 15 warning  33: FileWarning'], l)
159
160  " For help entries in the quickfix list, only the filename without directory
161  " should be displayed
162  Xhelpgrep setqflist()
163  let l = split(execute('Xlist 1', ''), "\n")
164  call assert_match('^ 1 [^\\/]\{-}:', l[0])
165
166  " Error cases
167  call assert_fails('Xlist abc', 'E488:')
168endfunc
169
170func Test_clist()
171  call XlistTests('c')
172  call XlistTests('l')
173endfunc
174
175" Tests for the :colder, :cnewer, :lolder and :lnewer commands
176" Note that this test assumes that a quickfix/location list is
177" already set by the caller.
178func XageTests(cchar)
179  call s:setup_commands(a:cchar)
180
181  if a:cchar == 'l'
182    " No location list for the current window
183    call assert_fails('lolder', 'E776:')
184    call assert_fails('lnewer', 'E776:')
185  endif
186
187  let list = [{'bufnr': bufnr('%'), 'lnum': 1}]
188  call g:Xsetlist(list)
189
190  " Jumping to a non existent list should return error
191  silent! Xolder 99
192  call assert_true(v:errmsg ==# 'E380: At bottom of quickfix stack')
193
194  silent! Xnewer 99
195  call assert_true(v:errmsg ==# 'E381: At top of quickfix stack')
196
197  " Add three quickfix/location lists
198  Xgetexpr ['Xtestfile1:1:3:Line1']
199  Xgetexpr ['Xtestfile2:2:2:Line2']
200  Xgetexpr ['Xtestfile3:3:1:Line3']
201
202  " Go back two lists
203  Xolder
204  let l = g:Xgetlist()
205  call assert_equal('Line2', l[0].text)
206
207  " Go forward two lists
208  Xnewer
209  let l = g:Xgetlist()
210  call assert_equal('Line3', l[0].text)
211
212  " Test for the optional count argument
213  Xolder 2
214  let l = g:Xgetlist()
215  call assert_equal('Line1', l[0].text)
216
217  Xnewer 2
218  let l = g:Xgetlist()
219  call assert_equal('Line3', l[0].text)
220endfunc
221
222func Test_cage()
223  call XageTests('c')
224  call XageTests('l')
225endfunc
226
227" Tests for the :cwindow, :lwindow :cclose, :lclose, :copen and :lopen
228" commands
229func XwindowTests(cchar)
230  call s:setup_commands(a:cchar)
231
232  " Opening the location list window without any errors should fail
233  if a:cchar == 'l'
234      call assert_fails('lopen', 'E776:')
235  endif
236
237  " Create a list with no valid entries
238  Xgetexpr ['non-error 1', 'non-error 2', 'non-error 3']
239
240  " Quickfix/Location window should not open with no valid errors
241  Xwindow
242  call assert_true(winnr('$') == 1)
243
244  " Create a list with valid entries
245  Xgetexpr ['Xtestfile1:1:3:Line1', 'Xtestfile2:2:2:Line2',
246		  \ 'Xtestfile3:3:1:Line3']
247
248  " Open the window
249  Xwindow
250  call assert_true(winnr('$') == 2 && winnr() == 2 &&
251	\ getline('.') ==# 'Xtestfile1|1 col 3| Line1')
252  redraw!
253
254  " Close the window
255  Xclose
256  call assert_true(winnr('$') == 1)
257
258  " Create a list with no valid entries
259  Xgetexpr ['non-error 1', 'non-error 2', 'non-error 3']
260
261  " Open the window
262  Xopen 5
263  call assert_true(winnr('$') == 2 && getline('.') ==# '|| non-error 1'
264		      \  && winheight(0) == 5)
265
266  " Opening the window again, should move the cursor to that window
267  wincmd t
268  Xopen 7
269  call assert_true(winnr('$') == 2 && winnr() == 2 &&
270	\ winheight(0) == 7 &&
271	\ getline('.') ==# '|| non-error 1')
272
273  " :cnext in quickfix window should move to the next entry
274  Xnext
275  call assert_equal(2, g:Xgetlist({'idx' : 0}).idx)
276
277  " Calling cwindow should close the quickfix window with no valid errors
278  Xwindow
279  call assert_true(winnr('$') == 1)
280
281  " Specifying the width should adjust the width for a vertically split
282  " quickfix window.
283  vert Xopen
284  call assert_equal(10, winwidth(0))
285  vert Xopen 12
286  call assert_equal(12, winwidth(0))
287  Xclose
288
289  " Horizontally or vertically splitting the quickfix window should create a
290  " normal window/buffer
291  Xopen
292  wincmd s
293  call assert_equal(0, getwininfo(win_getid())[0].quickfix)
294  call assert_equal(0, getwininfo(win_getid())[0].loclist)
295  call assert_notequal('quickfix', &buftype)
296  close
297  Xopen
298  wincmd v
299  call assert_equal(0, getwininfo(win_getid())[0].quickfix)
300  call assert_equal(0, getwininfo(win_getid())[0].loclist)
301  call assert_notequal('quickfix', &buftype)
302  close
303  Xopen
304  Xclose
305
306  if a:cchar == 'c'
307      " Opening the quickfix window in multiple tab pages should reuse the
308      " quickfix buffer
309      Xgetexpr ['Xtestfile1:1:3:Line1', 'Xtestfile2:2:2:Line2',
310		  \ 'Xtestfile3:3:1:Line3']
311      Xopen
312      let qfbufnum = bufnr('%')
313      tabnew
314      Xopen
315      call assert_equal(qfbufnum, bufnr('%'))
316      new | only | tabonly
317  endif
318endfunc
319
320func Test_cwindow()
321  call XwindowTests('c')
322  call XwindowTests('l')
323endfunc
324
325func Test_copenHeight()
326  copen
327  wincmd H
328  let height = winheight(0)
329  copen 10
330  call assert_equal(height, winheight(0))
331  quit
332endfunc
333
334func Test_copenHeight_tabline()
335  set tabline=foo showtabline=2
336  copen
337  wincmd H
338  let height = winheight(0)
339  copen 10
340  call assert_equal(height, winheight(0))
341  quit
342  set tabline& showtabline&
343endfunc
344
345
346" Tests for the :cfile, :lfile, :caddfile, :laddfile, :cgetfile and :lgetfile
347" commands.
348func XfileTests(cchar)
349  call s:setup_commands(a:cchar)
350
351  call writefile(['Xtestfile1:700:10:Line 700',
352	\ 'Xtestfile2:800:15:Line 800'], 'Xqftestfile1')
353
354  enew!
355  Xfile Xqftestfile1
356  let l = g:Xgetlist()
357  call assert_true(len(l) == 2 &&
358	\ l[0].lnum == 700 && l[0].col == 10 && l[0].text ==# 'Line 700' &&
359	\ l[1].lnum == 800 && l[1].col == 15 && l[1].text ==# 'Line 800')
360
361  " Test with a non existent file
362  call assert_fails('Xfile non_existent_file', 'E40:')
363
364  " Run cfile/lfile from a modified buffer
365  enew!
366  silent! put ='Quickfix'
367  silent! Xfile Xqftestfile1
368  call assert_true(v:errmsg ==# 'E37: No write since last change (add ! to override)')
369
370  call writefile(['Xtestfile3:900:30:Line 900'], 'Xqftestfile1')
371  Xaddfile Xqftestfile1
372  let l = g:Xgetlist()
373  call assert_true(len(l) == 3 &&
374	\ l[2].lnum == 900 && l[2].col == 30 && l[2].text ==# 'Line 900')
375
376  call writefile(['Xtestfile1:222:77:Line 222',
377	\ 'Xtestfile2:333:88:Line 333'], 'Xqftestfile1')
378
379  enew!
380  Xgetfile Xqftestfile1
381  let l = g:Xgetlist()
382  call assert_true(len(l) == 2 &&
383	\ l[0].lnum == 222 && l[0].col == 77 && l[0].text ==# 'Line 222' &&
384	\ l[1].lnum == 333 && l[1].col == 88 && l[1].text ==# 'Line 333')
385
386  " Test for a file with a long line and without a newline at the end
387  let text = repeat('x', 1024)
388  let t = 'a.txt:18:' . text
389  call writefile([t], 'Xqftestfile1', 'b')
390  silent! Xfile Xqftestfile1
391  call assert_equal(text, g:Xgetlist()[0].text)
392
393  call delete('Xqftestfile1')
394endfunc
395
396func Test_cfile()
397  call XfileTests('c')
398  call XfileTests('l')
399endfunc
400
401" Tests for the :cbuffer, :lbuffer, :caddbuffer, :laddbuffer, :cgetbuffer and
402" :lgetbuffer commands.
403func XbufferTests(cchar)
404  call s:setup_commands(a:cchar)
405
406  enew!
407  silent! call setline(1, ['Xtestfile7:700:10:Line 700',
408	\ 'Xtestfile8:800:15:Line 800'])
409  Xbuffer!
410  let l = g:Xgetlist()
411  call assert_true(len(l) == 2 &&
412	\ l[0].lnum == 700 && l[0].col == 10 && l[0].text ==# 'Line 700' &&
413	\ l[1].lnum == 800 && l[1].col == 15 && l[1].text ==# 'Line 800')
414
415  enew!
416  silent! call setline(1, ['Xtestfile9:900:55:Line 900',
417	\ 'Xtestfile10:950:66:Line 950'])
418  Xgetbuffer
419  let l = g:Xgetlist()
420  call assert_true(len(l) == 2 &&
421	\ l[0].lnum == 900 && l[0].col == 55 && l[0].text ==# 'Line 900' &&
422	\ l[1].lnum == 950 && l[1].col == 66 && l[1].text ==# 'Line 950')
423
424  enew!
425  silent! call setline(1, ['Xtestfile11:700:20:Line 700',
426	\ 'Xtestfile12:750:25:Line 750'])
427  Xaddbuffer
428  let l = g:Xgetlist()
429  call assert_true(len(l) == 4 &&
430	\ l[1].lnum == 950 && l[1].col == 66 && l[1].text ==# 'Line 950' &&
431	\ l[2].lnum == 700 && l[2].col == 20 && l[2].text ==# 'Line 700' &&
432	\ l[3].lnum == 750 && l[3].col == 25 && l[3].text ==# 'Line 750')
433  enew!
434
435  " Check for invalid buffer
436  call assert_fails('Xbuffer 199', 'E474:')
437
438  " Check for unloaded buffer
439  edit Xtestfile1
440  let bnr = bufnr('%')
441  enew!
442  call assert_fails('Xbuffer ' . bnr, 'E681:')
443
444  " Check for invalid range
445  " Using Xbuffer will not run the range check in the cbuffer/lbuffer
446  " commands. So directly call the commands.
447  if (a:cchar == 'c')
448      call assert_fails('900,999cbuffer', 'E16:')
449  else
450      call assert_fails('900,999lbuffer', 'E16:')
451  endif
452endfunc
453
454func Test_cbuffer()
455  call XbufferTests('c')
456  call XbufferTests('l')
457endfunc
458
459func XexprTests(cchar)
460  call s:setup_commands(a:cchar)
461
462  call assert_fails('Xexpr 10', 'E777:')
463endfunc
464
465func Test_cexpr()
466  call XexprTests('c')
467  call XexprTests('l')
468endfunc
469
470" Tests for :cnext, :cprev, :cfirst, :clast commands
471func Xtest_browse(cchar)
472  call s:setup_commands(a:cchar)
473
474  call g:Xsetlist([], 'f')
475  " Jumping to first or next location list entry without any error should
476  " result in failure
477  if a:cchar == 'c'
478    let err = 'E42:'
479    let cmd = '$cc'
480  else
481    let err = 'E776:'
482    let cmd = '$ll'
483  endif
484  call assert_fails('Xnext', err)
485  call assert_fails('Xprev', err)
486  call assert_fails('Xnfile', err)
487  call assert_fails('Xpfile', err)
488  call assert_fails(cmd, err)
489
490  Xexpr ''
491  call assert_fails(cmd, 'E42:')
492
493  call s:create_test_file('Xqftestfile1')
494  call s:create_test_file('Xqftestfile2')
495
496  Xgetexpr ['Xqftestfile1:5:Line5',
497		\ 'Xqftestfile1:6:Line6',
498		\ 'Xqftestfile2:10:Line10',
499		\ 'Xqftestfile2:11:Line11',
500		\ 'RegularLine1',
501		\ 'RegularLine2']
502
503  Xfirst
504  call assert_fails('-5Xcc', 'E16:')
505  call assert_fails('Xprev', 'E553:')
506  call assert_fails('Xpfile', 'E553:')
507  Xnfile
508  call assert_equal('Xqftestfile2', @%)
509  call assert_equal(10, line('.'))
510  Xpfile
511  call assert_equal('Xqftestfile1', @%)
512  call assert_equal(6, line('.'))
513  5Xcc
514  call assert_equal(5, g:Xgetlist({'idx':0}).idx)
515  2Xcc
516  call assert_equal(2, g:Xgetlist({'idx':0}).idx)
517  if a:cchar == 'c'
518    cc
519  else
520    ll
521  endif
522  call assert_equal(2, g:Xgetlist({'idx':0}).idx)
523  10Xcc
524  call assert_equal(6, g:Xgetlist({'idx':0}).idx)
525  Xlast
526  Xprev
527  call assert_equal('Xqftestfile2', @%)
528  call assert_equal(11, line('.'))
529  call assert_fails('Xnext', 'E553:')
530  call assert_fails('Xnfile', 'E553:')
531  " To process the range using quickfix list entries, directly use the
532  " quickfix commands (don't use the user defined commands)
533  if a:cchar == 'c'
534    $cc
535  else
536    $ll
537  endif
538  call assert_equal(6, g:Xgetlist({'idx':0}).idx)
539  Xrewind
540  call assert_equal('Xqftestfile1', @%)
541  call assert_equal(5, line('.'))
542
543  10Xnext
544  call assert_equal('Xqftestfile2', @%)
545  call assert_equal(11, line('.'))
546  10Xprev
547  call assert_equal('Xqftestfile1', @%)
548  call assert_equal(5, line('.'))
549
550  " Jumping to an error from the error window using cc command
551  Xgetexpr ['Xqftestfile1:5:Line5',
552		\ 'Xqftestfile1:6:Line6',
553		\ 'Xqftestfile2:10:Line10',
554		\ 'Xqftestfile2:11:Line11']
555  Xopen
556  10Xcc
557  call assert_equal(11, line('.'))
558  call assert_equal('Xqftestfile2', @%)
559  Xopen
560  call cursor(2, 1)
561  if a:cchar == 'c'
562    .cc
563  else
564    .ll
565  endif
566  call assert_equal(6, line('.'))
567  call assert_equal('Xqftestfile1', @%)
568
569  " Jumping to an error from the error window (when only the error window is
570  " present)
571  Xopen | only
572  Xlast 1
573  call assert_equal(5, line('.'))
574  call assert_equal('Xqftestfile1', @%)
575
576  Xexpr ""
577  call assert_fails('Xnext', 'E42:')
578
579  call delete('Xqftestfile1')
580  call delete('Xqftestfile2')
581
582  " Should be able to use next/prev with invalid entries
583  Xexpr ""
584  call assert_equal(0, g:Xgetlist({'idx' : 0}).idx)
585  call assert_equal(0, g:Xgetlist({'size' : 0}).size)
586  Xaddexpr ['foo', 'bar', 'baz', 'quux', 'sh|moo']
587  call assert_equal(5, g:Xgetlist({'size' : 0}).size)
588  Xlast
589  call assert_equal(5, g:Xgetlist({'idx' : 0}).idx)
590  Xfirst
591  call assert_equal(1, g:Xgetlist({'idx' : 0}).idx)
592  2Xnext
593  call assert_equal(3, g:Xgetlist({'idx' : 0}).idx)
594endfunc
595
596func Test_browse()
597  call Xtest_browse('c')
598  call Xtest_browse('l')
599endfunc
600
601func Test_nomem()
602  call test_alloc_fail(GetAllocId('qf_dirname_start'), 0, 0)
603  call assert_fails('vimgrep vim runtest.vim', 'E342:')
604
605  call GetAllocId('qf_dirname_now')->test_alloc_fail(0, 0)
606  call assert_fails('vimgrep vim runtest.vim', 'E342:')
607
608  call test_alloc_fail(GetAllocId('qf_namebuf'), 0, 0)
609  call assert_fails('cfile runtest.vim', 'E342:')
610
611  call test_alloc_fail(GetAllocId('qf_errmsg'), 0, 0)
612  call assert_fails('cfile runtest.vim', 'E342:')
613
614  call test_alloc_fail(GetAllocId('qf_pattern'), 0, 0)
615  call assert_fails('cfile runtest.vim', 'E342:')
616
617endfunc
618
619func s:test_xhelpgrep(cchar)
620  call s:setup_commands(a:cchar)
621  Xhelpgrep quickfix
622  Xopen
623  if a:cchar == 'c'
624    let title_text = ':helpgrep quickfix'
625  else
626    let title_text = ':lhelpgrep quickfix'
627  endif
628  call assert_true(w:quickfix_title =~ title_text, w:quickfix_title)
629
630  " Jumping to a help topic should open the help window
631  only
632  Xnext
633  call assert_true(&buftype == 'help')
634  call assert_true(winnr('$') == 2)
635  " Jumping to the next match should reuse the help window
636  Xnext
637  call assert_true(&buftype == 'help')
638  call assert_true(winnr() == 1)
639  call assert_true(winnr('$') == 2)
640  " Jumping to the next match from the quickfix window should reuse the help
641  " window
642  Xopen
643  Xnext
644  call assert_true(&buftype == 'help')
645  call assert_true(winnr() == 1)
646  call assert_true(winnr('$') == 2)
647
648  " This wipes out the buffer, make sure that doesn't cause trouble.
649  Xclose
650
651  " When the current window is vertically split, jumping to a help match
652  " should open the help window at the top.
653  only | enew
654  let w1 = win_getid()
655  vert new
656  let w2 = win_getid()
657  Xnext
658  let w3 = win_getid()
659  call assert_true(&buftype == 'help')
660  call assert_true(winnr() == 1)
661  " See jump_to_help_window() for details
662  let w2_width = winwidth(w2)
663  if w2_width != &columns && w2_width < 80
664    call assert_equal(['col', [['leaf', w3],
665          \ ['row', [['leaf', w2], ['leaf', w1]]]]], winlayout())
666  else
667    call assert_equal(['row', [['col', [['leaf', w3], ['leaf', w2]]],
668          \ ['leaf', w1]]] , winlayout())
669  endif
670
671  new | only
672  set buftype=help
673  set modified
674  call assert_fails('Xnext', 'E37:')
675  set nomodified
676  new | only
677
678  if a:cchar == 'l'
679      " When a help window is present, running :lhelpgrep should reuse the
680      " help window and not the current window
681      new | only
682      call g:Xsetlist([], 'f')
683      help index.txt
684      wincmd w
685      lhelpgrep quickfix
686      call assert_equal(1, winnr())
687      call assert_notequal([], getloclist(1))
688      call assert_equal([], getloclist(2))
689  endif
690
691  new | only
692
693  " Search for non existing help string
694  call assert_fails('Xhelpgrep a1b2c3', 'E480:')
695  " Invalid regular expression
696  call assert_fails('Xhelpgrep \@<!', 'E866:')
697endfunc
698
699func Test_helpgrep()
700  call s:test_xhelpgrep('c')
701  helpclose
702  call s:test_xhelpgrep('l')
703endfunc
704
705def Test_helpgrep_vim9_restore_cpo()
706  assert_equal('aABceFs', &cpo)
707
708  var rtp_save = &rtp
709  var dir = 'Xruntime/after'
710  &rtp ..= ',' .. dir
711  mkdir(dir .. '/ftplugin', 'p')
712  writefile(['vim9'], dir .. '/ftplugin/qf.vim')
713  filetype plugin on
714  silent helpgrep grail
715  cwindow
716  silent helpgrep grail
717
718  assert_equal('aABceFs', &cpo)
719  delete(dir, 'rf')
720  &rtp = rtp_save
721  cclose
722  helpclose
723enddef
724
725func Test_errortitle()
726  augroup QfBufWinEnter
727    au!
728    au BufWinEnter * :let g:a=get(w:, 'quickfix_title', 'NONE')
729  augroup END
730  copen
731  let a=[{'lnum': 308, 'bufnr': bufnr(''), 'col': 58, 'valid': 1, 'vcol': 0, 'nr': 0, 'type': '', 'pattern': '', 'text': '    au BufWinEnter * :let g:a=get(w:, ''quickfix_title'', ''NONE'')'}]
732  call setqflist(a)
733  call assert_equal(':setqflist()', g:a)
734  augroup QfBufWinEnter
735    au!
736  augroup END
737  augroup! QfBufWinEnter
738endfunc
739
740func Test_vimgreptitle()
741  augroup QfBufWinEnter
742    au!
743    au BufWinEnter * :let g:a=get(w:, 'quickfix_title', 'NONE')
744  augroup END
745  try
746    vimgrep /pattern/j file
747  catch /E480/
748  endtry
749  copen
750  call assert_equal(':    vimgrep /pattern/j file', g:a)
751  augroup QfBufWinEnter
752    au!
753  augroup END
754  augroup! QfBufWinEnter
755endfunc
756
757func XqfTitleTests(cchar)
758  call s:setup_commands(a:cchar)
759
760  Xgetexpr ['file:1:1:message']
761  let l = g:Xgetlist()
762  if a:cchar == 'c'
763    call setqflist(l, 'r')
764  else
765    call setloclist(0, l, 'r')
766  endif
767
768  Xopen
769  if a:cchar == 'c'
770    let title = ':setqflist()'
771  else
772    let title = ':setloclist()'
773  endif
774  call assert_equal(title, w:quickfix_title)
775  Xclose
776endfunc
777
778" Tests for quickfix window's title
779func Test_qf_title()
780  call XqfTitleTests('c')
781  call XqfTitleTests('l')
782endfunc
783
784" Tests for 'errorformat'
785func Test_efm()
786  let save_efm = &efm
787  set efm=%EEEE%m,%WWWW%m,%+CCCC%.%#,%-GGGG%.%#
788  cgetexpr ['WWWW', 'EEEE', 'CCCC']
789  let l = strtrans(string(map(getqflist(), '[v:val.text, v:val.valid]')))
790  call assert_equal("[['W', 1], ['E^@CCCC', 1]]", l)
791  cgetexpr ['WWWW', 'GGGG', 'EEEE', 'CCCC']
792  let l = strtrans(string(map(getqflist(), '[v:val.text, v:val.valid]')))
793  call assert_equal("[['W', 1], ['E^@CCCC', 1]]", l)
794  cgetexpr ['WWWW', 'GGGG', 'ZZZZ', 'EEEE', 'CCCC', 'YYYY']
795  let l = strtrans(string(map(getqflist(), '[v:val.text, v:val.valid]')))
796  call assert_equal("[['W', 1], ['ZZZZ', 0], ['E^@CCCC', 1], ['YYYY', 0]]", l)
797  let &efm = save_efm
798endfunc
799
800" This will test for problems in quickfix:
801" A. incorrectly copying location lists which caused the location list to show
802"    a different name than the file that was actually being displayed.
803" B. not reusing the window for which the location list window is opened but
804"    instead creating new windows.
805" C. make sure that the location list window is not reused instead of the
806"    window it belongs to.
807"
808" Set up the test environment:
809func ReadTestProtocol(name)
810  let base = substitute(a:name, '\v^test://(.*)%(\.[^.]+)?', '\1', '')
811  let word = substitute(base, '\v(.*)\..*', '\1', '')
812
813  setl modifiable
814  setl noreadonly
815  setl noswapfile
816  setl bufhidden=delete
817  %del _
818  " For problem 2:
819  " 'buftype' has to be set to reproduce the constant opening of new windows
820  setl buftype=nofile
821
822  call setline(1, word)
823
824  setl nomodified
825  setl nomodifiable
826  setl readonly
827  exe 'doautocmd BufRead ' . substitute(a:name, '\v^test://(.*)', '\1', '')
828endfunc
829
830func Test_locationlist()
831  enew
832
833  augroup testgroup
834    au!
835    autocmd BufReadCmd test://* call ReadTestProtocol(expand("<amatch>"))
836  augroup END
837
838  let words = [ "foo", "bar", "baz", "quux", "shmoo", "spam", "eggs" ]
839
840  let qflist = []
841  for word in words
842    call add(qflist, {'filename': 'test://' . word . '.txt', 'text': 'file ' . word . '.txt', })
843    " NOTE: problem 1:
844    " intentionally not setting 'lnum' so that the quickfix entries are not
845    " valid
846    eval qflist->setloclist(0, ' ')
847  endfor
848
849  " Test A
850  lrewind
851  enew
852  lopen
853  4lnext
854  vert split
855  wincmd L
856  lopen
857  wincmd p
858  lnext
859  let fileName = expand("%")
860  wincmd p
861  let locationListFileName = substitute(getline(line('.')), '\([^|]*\)|.*', '\1', '')
862  let fileName = substitute(fileName, '\\', '/', 'g')
863  let locationListFileName = substitute(locationListFileName, '\\', '/', 'g')
864  call assert_equal("test://bar.txt", fileName)
865  call assert_equal("test://bar.txt", locationListFileName)
866
867  wincmd n | only
868
869  " Test B:
870  lrewind
871  lopen
872  2
873  exe "normal \<CR>"
874  wincmd p
875  3
876  exe "normal \<CR>"
877  wincmd p
878  4
879  exe "normal \<CR>"
880  call assert_equal(2, winnr('$'))
881  wincmd n | only
882
883  " Test C:
884  lrewind
885  lopen
886  " Let's move the location list window to the top to check whether it (the
887  " first window found) will be reused when we try to open new windows:
888  wincmd K
889  2
890  exe "normal \<CR>"
891  wincmd p
892  3
893  exe "normal \<CR>"
894  wincmd p
895  4
896  exe "normal \<CR>"
897  1wincmd w
898  call assert_equal('quickfix', &buftype)
899  2wincmd w
900  let bufferName = expand("%")
901  let bufferName = substitute(bufferName, '\\', '/', 'g')
902  call assert_equal('test://quux.txt', bufferName)
903
904  wincmd n | only
905
906  augroup! testgroup
907endfunc
908
909func Test_locationlist_curwin_was_closed()
910  augroup testgroup
911    au!
912    autocmd BufReadCmd test_curwin.txt call R(expand("<amatch>"))
913  augroup END
914
915  func! R(n)
916    quit
917  endfunc
918
919  new
920  let q = []
921  call add(q, {'filename': 'test_curwin.txt' })
922  call setloclist(0, q)
923  call assert_fails('lrewind', 'E924:')
924
925  augroup! testgroup
926endfunc
927
928func Test_locationlist_cross_tab_jump()
929  call writefile(['loclistfoo'], 'loclistfoo')
930  call writefile(['loclistbar'], 'loclistbar')
931  set switchbuf=usetab
932
933  edit loclistfoo
934  tabedit loclistbar
935  silent lgrep loclistfoo loclist*
936  call assert_equal(1, tabpagenr())
937
938  enew | only | tabonly
939  set switchbuf&vim
940  call delete('loclistfoo')
941  call delete('loclistbar')
942endfunc
943
944" More tests for 'errorformat'
945func Test_efm1()
946  " The 'errorformat' setting is different on non-Unix systems.
947  " This test works only on Unix-like systems.
948  CheckUnix
949
950  let l =<< trim [DATA]
951    "Xtestfile", line 4.12: 1506-045 (S) Undeclared identifier fd_set.
952    "Xtestfile", line 6 col 19; this is an error
953    gcc -c -DHAVE_CONFIsing-prototypes -I/usr/X11R6/include  version.c
954    Xtestfile:9: parse error before `asd'
955    make: *** [vim] Error 1
956    in file "Xtestfile" linenr 10: there is an error
957
958    2 returned
959    "Xtestfile", line 11 col 1; this is an error
960    "Xtestfile", line 12 col 2; this is another error
961    "Xtestfile", line 14:10; this is an error in column 10
962    =Xtestfile=, line 15:10; this is another error, but in vcol 10 this time
963    "Xtestfile", linenr 16: yet another problem
964    Error in "Xtestfile" at line 17:
965    x should be a dot
966    	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 17
967                ^
968    Error in "Xtestfile" at line 18:
969    x should be a dot
970    	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 18
971    .............^
972    Error in "Xtestfile" at line 19:
973    x should be a dot
974    	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 19
975    --------------^
976    Error in "Xtestfile" at line 20:
977    x should be a dot
978    	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 20
979    	       ^
980
981    Does anyone know what is the problem and how to correction it?
982    "Xtestfile", line 21 col 9: What is the title of the quickfix window?
983    "Xtestfile", line 22 col 9: What is the title of the quickfix window?
984  [DATA]
985
986  call writefile(l, 'Xerrorfile1')
987  call writefile(l[:-2], 'Xerrorfile2')
988
989  let m =<< [DATA]
990	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  2
991	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  3
992	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  4
993	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  5
994	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  6
995	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  7
996	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  8
997	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  9
998	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 10
999	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 11
1000	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 12
1001	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 13
1002	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 14
1003	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 15
1004	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 16
1005	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 17
1006	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 18
1007	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 19
1008	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 20
1009	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 21
1010	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 22
1011[DATA]
1012  call writefile(m, 'Xtestfile')
1013
1014  let save_efm = &efm
1015  set efm+==%f=\\,\ line\ %l%*\\D%v%*[^\ ]\ %m
1016  set efm^=%AError\ in\ \"%f\"\ at\ line\ %l:,%Z%p^,%C%m
1017
1018  exe 'cf Xerrorfile2'
1019  clast
1020  copen
1021  call assert_equal(':cf Xerrorfile2', w:quickfix_title)
1022  wincmd p
1023
1024  exe 'cf Xerrorfile1'
1025  call assert_equal([4, 12], [line('.'), col('.')])
1026  cn
1027  call assert_equal([6, 19], [line('.'), col('.')])
1028  cn
1029  call assert_equal([9, 2], [line('.'), col('.')])
1030  cn
1031  call assert_equal([10, 2], [line('.'), col('.')])
1032  cn
1033  call assert_equal([11, 1], [line('.'), col('.')])
1034  cn
1035  call assert_equal([12, 2], [line('.'), col('.')])
1036  cn
1037  call assert_equal([14, 10], [line('.'), col('.')])
1038  cn
1039  call assert_equal([15, 3, 10], [line('.'), col('.'), virtcol('.')])
1040  cn
1041  call assert_equal([16, 2], [line('.'), col('.')])
1042  cn
1043  call assert_equal([17, 6], [line('.'), col('.')])
1044  cn
1045  call assert_equal([18, 7], [line('.'), col('.')])
1046  cn
1047  call assert_equal([19, 8], [line('.'), col('.')])
1048  cn
1049  call assert_equal([20, 9], [line('.'), col('.')])
1050  clast
1051  cprev
1052  cprev
1053  wincmd w
1054  call assert_equal(':cf Xerrorfile1', w:quickfix_title)
1055  wincmd p
1056
1057  let &efm = save_efm
1058  call delete('Xerrorfile1')
1059  call delete('Xerrorfile2')
1060  call delete('Xtestfile')
1061endfunc
1062
1063" Test for quickfix directory stack support
1064func s:dir_stack_tests(cchar)
1065  call s:setup_commands(a:cchar)
1066
1067  let save_efm=&efm
1068  set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f'
1069
1070  let lines = ["Entering dir 'dir1/a'",
1071		\ 'habits2.txt:1:Nine Healthy Habits',
1072		\ "Entering dir 'b'",
1073		\ 'habits3.txt:2:0 Hours of television',
1074		\ 'habits2.txt:7:5 Small meals',
1075		\ "Entering dir 'dir1/c'",
1076		\ 'habits4.txt:3:1 Hour of exercise',
1077		\ "Leaving dir 'dir1/c'",
1078		\ "Leaving dir 'dir1/a'",
1079		\ 'habits1.txt:4:2 Liters of water',
1080		\ "Entering dir 'dir2'",
1081		\ 'habits5.txt:5:3 Cups of hot green tea',
1082		\ "Leaving dir 'dir2'"
1083		\]
1084
1085  Xexpr ""
1086  for l in lines
1087      Xaddexpr l
1088  endfor
1089
1090  let qf = g:Xgetlist()
1091
1092  call assert_equal('dir1/a/habits2.txt', bufname(qf[1].bufnr))
1093  call assert_equal(1, qf[1].lnum)
1094  call assert_equal('dir1/a/b/habits3.txt', bufname(qf[3].bufnr))
1095  call assert_equal(2, qf[3].lnum)
1096  call assert_equal('dir1/a/habits2.txt', bufname(qf[4].bufnr))
1097  call assert_equal(7, qf[4].lnum)
1098  call assert_equal('dir1/c/habits4.txt', bufname(qf[6].bufnr))
1099  call assert_equal(3, qf[6].lnum)
1100  call assert_equal('habits1.txt', bufname(qf[9].bufnr))
1101  call assert_equal(4, qf[9].lnum)
1102  call assert_equal('dir2/habits5.txt', bufname(qf[11].bufnr))
1103  call assert_equal(5, qf[11].lnum)
1104
1105  let &efm=save_efm
1106endfunc
1107
1108" Tests for %D and %X errorformat options
1109func Test_efm_dirstack()
1110  " Create the directory stack and files
1111  call mkdir('dir1')
1112  call mkdir('dir1/a')
1113  call mkdir('dir1/a/b')
1114  call mkdir('dir1/c')
1115  call mkdir('dir2')
1116
1117  let lines = ["Nine Healthy Habits",
1118		\ "0 Hours of television",
1119		\ "1 Hour of exercise",
1120		\ "2 Liters of water",
1121		\ "3 Cups of hot green tea",
1122		\ "4 Short mental breaks",
1123		\ "5 Small meals",
1124		\ "6 AM wake up time",
1125		\ "7 Minutes of laughter",
1126		\ "8 Hours of sleep (at least)",
1127		\ "9 PM end of the day and off to bed"
1128		\ ]
1129  call writefile(lines, 'habits1.txt')
1130  call writefile(lines, 'dir1/a/habits2.txt')
1131  call writefile(lines, 'dir1/a/b/habits3.txt')
1132  call writefile(lines, 'dir1/c/habits4.txt')
1133  call writefile(lines, 'dir2/habits5.txt')
1134
1135  call s:dir_stack_tests('c')
1136  call s:dir_stack_tests('l')
1137
1138  call delete('dir1', 'rf')
1139  call delete('dir2', 'rf')
1140  call delete('habits1.txt')
1141endfunc
1142
1143" Test for resync after continuing an ignored message
1144func Xefm_ignore_continuations(cchar)
1145  call s:setup_commands(a:cchar)
1146
1147  let save_efm = &efm
1148
1149  let &efm =
1150	\ '%Eerror %m %l,' .
1151	\ '%-Wignored %m %l,' .
1152	\ '%+Cmore ignored %m %l,' .
1153	\ '%Zignored end'
1154  Xgetexpr ['ignored warning 1', 'more ignored continuation 2', 'ignored end', 'error resync 4']
1155  let l = map(g:Xgetlist(), '[v:val.text, v:val.valid, v:val.lnum, v:val.type]')
1156  call assert_equal([['resync', 1, 4, 'E']], l)
1157
1158  let &efm = save_efm
1159endfunc
1160
1161func Test_efm_ignore_continuations()
1162  call Xefm_ignore_continuations('c')
1163  call Xefm_ignore_continuations('l')
1164endfunc
1165
1166" Tests for invalid error format specifies
1167func Xinvalid_efm_Tests(cchar)
1168  call s:setup_commands(a:cchar)
1169
1170  let save_efm = &efm
1171
1172  set efm=%f:%l:%m,%f:%f:%l:%m
1173  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E372:')
1174
1175  set efm=%f:%l:%m,%f:%l:%r:%m
1176  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E373:')
1177
1178  set efm=%f:%l:%m,%O:%f:%l:%m
1179  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E373:')
1180
1181  set efm=%f:%l:%m,%f:%l:%*[^a-z
1182  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E374:')
1183
1184  set efm=%f:%l:%m,%f:%l:%*c
1185  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E375:')
1186
1187  set efm=%f:%l:%m,%L%M%N
1188  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E376:')
1189
1190  set efm=%f:%l:%m,%f:%l:%m:%R
1191  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E377:')
1192
1193  " Invalid regular expression
1194  set efm=%\\%%k
1195  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E867:')
1196
1197  set efm=
1198  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E378:')
1199
1200  set efm=%DEntering\ dir\ abc,%f:%l:%m
1201  call assert_fails('Xexpr ["Entering dir abc", "abc.txt:1:Hello world"]', 'E379:')
1202
1203  let &efm = save_efm
1204endfunc
1205
1206func Test_invalid_efm()
1207  call Xinvalid_efm_Tests('c')
1208  call Xinvalid_efm_Tests('l')
1209endfunc
1210
1211" TODO:
1212" Add tests for the following formats in 'errorformat'
1213"	%r  %O
1214func Test_efm2()
1215  let save_efm = &efm
1216
1217  " Test for %s format in efm
1218  set efm=%f:%s
1219  cexpr 'Xtestfile:Line search text'
1220  let l = getqflist()
1221  call assert_equal('^\VLine search text\$', l[0].pattern)
1222  call assert_equal(0, l[0].lnum)
1223
1224  let l = split(execute('clist', ''), "\n")
1225  call assert_equal([' 1 Xtestfile:^\VLine search text\$:  '], l)
1226
1227  " Test for a long line
1228  cexpr 'Xtestfile:' . repeat('a', 1026)
1229  let l = getqflist()
1230  call assert_equal('^\V' . repeat('a', 1019) . '\$', l[0].pattern)
1231
1232  " Test for %P, %Q and %t format specifiers
1233  let lines =<< trim [DATA]
1234    [Xtestfile1]
1235    (1,17)  error: ';' missing
1236    (21,2)  warning: variable 'z' not defined
1237    (67,3)  error: end of file found before string ended
1238    --
1239
1240    [Xtestfile2]
1241    --
1242
1243    [Xtestfile3]
1244    NEW compiler v1.1
1245    (2,2)   warning: variable 'x' not defined
1246    (67,3)  warning: 's' already defined
1247    --
1248  [DATA]
1249
1250  set efm=%+P[%f]%r,(%l\\,%c)%*[\ ]%t%*[^:]:\ %m,%+Q--%r
1251  " To exercise the push/pop file functionality in quickfix, the test files
1252  " need to be created.
1253  call writefile(['Line1'], 'Xtestfile1')
1254  call writefile(['Line2'], 'Xtestfile2')
1255  call writefile(['Line3'], 'Xtestfile3')
1256  cexpr ""
1257  for l in lines
1258      caddexpr l
1259  endfor
1260  let l = getqflist()
1261  call assert_equal(12, len(l))
1262  call assert_equal(21, l[2].lnum)
1263  call assert_equal(2, l[2].col)
1264  call assert_equal('w', l[2].type)
1265  call assert_equal('e', l[3].type)
1266  call delete('Xtestfile1')
1267  call delete('Xtestfile2')
1268  call delete('Xtestfile3')
1269
1270  " Test for %P, %Q with non-existing files
1271  cexpr lines
1272  let l = getqflist()
1273  call assert_equal(14, len(l))
1274  call assert_equal('[Xtestfile1]', l[0].text)
1275  call assert_equal('[Xtestfile2]', l[6].text)
1276  call assert_equal('[Xtestfile3]', l[9].text)
1277
1278  " Tests for %E, %C and %Z format specifiers
1279  let lines =<< trim [DATA]
1280    Error 275
1281    line 42
1282    column 3
1283    ' ' expected after '--'
1284  [DATA]
1285
1286  set efm=%EError\ %n,%Cline\ %l,%Ccolumn\ %c,%Z%m
1287  cgetexpr lines
1288  let l = getqflist()
1289  call assert_equal(275, l[0].nr)
1290  call assert_equal(42, l[0].lnum)
1291  call assert_equal(3, l[0].col)
1292  call assert_equal('E', l[0].type)
1293  call assert_equal("\n' ' expected after '--'", l[0].text)
1294
1295  " Test for %>
1296  let lines =<< trim [DATA]
1297    Error in line 147 of foo.c:
1298    unknown variable 'i'
1299  [DATA]
1300
1301  set efm=unknown\ variable\ %m,%E%>Error\ in\ line\ %l\ of\ %f:,%Z%m
1302  cgetexpr lines
1303  let l = getqflist()
1304  call assert_equal(147, l[0].lnum)
1305  call assert_equal('E', l[0].type)
1306  call assert_equal("\nunknown variable 'i'", l[0].text)
1307
1308  " Test for %A, %C and other formats
1309  let lines =<< trim [DATA]
1310    ==============================================================
1311    FAIL: testGetTypeIdCachesResult (dbfacadeTest.DjsDBFacadeTest)
1312    --------------------------------------------------------------
1313    Traceback (most recent call last):
1314      File "unittests/dbfacadeTest.py", line 89, in testFoo
1315        self.assertEquals(34, dtid)
1316      File "/usr/lib/python2.2/unittest.py", line 286, in
1317     failUnlessEqual
1318        raise self.failureException, \\
1319    W:AssertionError: 34 != 33
1320
1321    --------------------------------------------------------------
1322    Ran 27 tests in 0.063s
1323  [DATA]
1324
1325  set efm=%C\ %.%#,%A\ \ File\ \"%f\"\\,\ line\ %l%.%#,%Z%[%^\ ]%\\@=%t:%m
1326  cgetexpr lines
1327  let l = getqflist()
1328  call assert_equal(8, len(l))
1329  call assert_equal(89, l[4].lnum)
1330  call assert_equal(1, l[4].valid)
1331  call assert_equal('unittests/dbfacadeTest.py', bufname(l[4].bufnr))
1332  call assert_equal('W', l[4].type)
1333
1334  " Test for %o
1335  set efm=%f(%o):%l\ %m
1336  cgetexpr ['Xotestfile(Language.PureScript.Types):20 Error']
1337  call writefile(['Line1'], 'Xotestfile')
1338  let l = getqflist()
1339  call assert_equal(1, len(l), string(l))
1340  call assert_equal('Language.PureScript.Types', l[0].module)
1341  copen
1342  call assert_equal('Language.PureScript.Types|20| Error', getline(1))
1343  call feedkeys("\<CR>", 'xn')
1344  call assert_equal('Xotestfile', expand('%:t'))
1345  cclose
1346  bd
1347  call delete("Xotestfile")
1348
1349  " Test for a long module name
1350  cexpr 'Xtest(' . repeat('m', 1026) . '):15 message'
1351  let l = getqflist()
1352  call assert_equal(repeat('m', 1024), l[0].module)
1353  call assert_equal(15, l[0].lnum)
1354  call assert_equal('message', l[0].text)
1355
1356  " The following sequence of commands used to crash Vim
1357  set efm=%W%m
1358  cgetexpr ['msg1']
1359  let l = getqflist()
1360  call assert_equal(1, len(l), string(l))
1361  call assert_equal('msg1', l[0].text)
1362  set efm=%C%m
1363  lexpr 'msg2'
1364  let l = getloclist(0)
1365  call assert_equal(1, len(l), string(l))
1366  call assert_equal('msg2', l[0].text)
1367  lopen
1368  call setqflist([], 'r')
1369  caddbuf
1370  let l = getqflist()
1371  call assert_equal(1, len(l), string(l))
1372  call assert_equal('|| msg2', l[0].text)
1373
1374  " When matching error lines, case should be ignored. Test for this.
1375  set noignorecase
1376  let l=getqflist({'lines' : ['Xtest:FOO10:Line 20'], 'efm':'%f:foo%l:%m'})
1377  call assert_equal(10, l.items[0].lnum)
1378  call assert_equal('Line 20', l.items[0].text)
1379  set ignorecase&
1380
1381  new | only
1382  let &efm = save_efm
1383endfunc
1384
1385" Test for '%t' (error type) field in 'efm'
1386func Test_efm_error_type()
1387  let save_efm = &efm
1388
1389  " error type
1390  set efm=%f:%l:%t:%m
1391  cexpr ["Xfile1:10:E:msg1", "Xfile1:20:W:msg2", "Xfile1:30:I:msg3",
1392        \ "Xfile1:40:N:msg4", "Xfile1:50:R:msg5"]
1393  let output = split(execute('clist'), "\n")
1394  call assert_equal([
1395        \ ' 1 Xfile1:10 error: msg1',
1396        \ ' 2 Xfile1:20 warning: msg2',
1397        \ ' 3 Xfile1:30 info: msg3',
1398        \ ' 4 Xfile1:40 note: msg4',
1399        \ ' 5 Xfile1:50 R: msg5'], output)
1400
1401  " error type and a error number
1402  set efm=%f:%l:%t:%n:%m
1403  cexpr ["Xfile1:10:E:2:msg1", "Xfile1:20:W:4:msg2", "Xfile1:30:I:6:msg3",
1404        \ "Xfile1:40:N:8:msg4", "Xfile1:50:R:3:msg5"]
1405  let output = split(execute('clist'), "\n")
1406  call assert_equal([
1407        \ ' 1 Xfile1:10 error   2: msg1',
1408        \ ' 2 Xfile1:20 warning   4: msg2',
1409        \ ' 3 Xfile1:30 info   6: msg3',
1410        \ ' 4 Xfile1:40 note   8: msg4',
1411        \ ' 5 Xfile1:50 R   3: msg5'], output)
1412  let &efm = save_efm
1413endfunc
1414
1415func XquickfixChangedByAutocmd(cchar)
1416  call s:setup_commands(a:cchar)
1417  if a:cchar == 'c'
1418    let ErrorNr = 'E925'
1419    func! ReadFunc()
1420      colder
1421      cgetexpr []
1422    endfunc
1423  else
1424    let ErrorNr = 'E926'
1425    func! ReadFunc()
1426      lolder
1427      lgetexpr []
1428    endfunc
1429  endif
1430
1431  augroup testgroup
1432    au!
1433    autocmd BufReadCmd test_changed.txt call ReadFunc()
1434  augroup END
1435
1436  new | only
1437  let words = [ "a", "b" ]
1438  let qflist = []
1439  for word in words
1440    call add(qflist, {'filename': 'test_changed.txt'})
1441    call g:Xsetlist(qflist, ' ')
1442  endfor
1443  call assert_fails('Xrewind', ErrorNr . ':')
1444
1445  augroup! testgroup
1446endfunc
1447
1448func Test_quickfix_was_changed_by_autocmd()
1449  call XquickfixChangedByAutocmd('c')
1450  call XquickfixChangedByAutocmd('l')
1451endfunc
1452
1453func Test_setloclist_in_autocommand()
1454  call writefile(['test1', 'test2'], 'Xfile')
1455  edit Xfile
1456  let s:bufnr = bufnr()
1457  call setloclist(1,
1458        \ [{'bufnr' : s:bufnr, 'lnum' : 1, 'text' : 'test1'},
1459        \  {'bufnr' : s:bufnr, 'lnum' : 2, 'text' : 'test2'}])
1460
1461  augroup Test_LocList
1462    au!
1463    autocmd BufEnter * call setloclist(1,
1464          \ [{'bufnr' : s:bufnr, 'lnum' : 1, 'text' : 'test1'},
1465          \  {'bufnr' : s:bufnr, 'lnum' : 2, 'text' : 'test2'}], 'r')
1466  augroup END
1467
1468  lopen
1469  call assert_fails('exe "normal j\<CR>"', 'E926:')
1470
1471  augroup Test_LocList
1472    au!
1473  augroup END
1474  call delete('Xfile')
1475endfunc
1476
1477func Test_caddbuffer_to_empty()
1478  helpgr quickfix
1479  call setqflist([], 'r')
1480  cad
1481  try
1482    cn
1483  catch
1484    " number of matches is unknown
1485    call assert_true(v:exception =~ 'E553:')
1486  endtry
1487  quit!
1488endfunc
1489
1490func Test_cgetexpr_works()
1491  " this must not crash Vim
1492  cgetexpr [$x]
1493  lgetexpr [$x]
1494endfunc
1495
1496" Tests for the setqflist() and setloclist() functions
1497func SetXlistTests(cchar, bnum)
1498  call s:setup_commands(a:cchar)
1499
1500  call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 1},
1501	      \  {'bufnr': a:bnum, 'lnum': 2}])
1502  let l = g:Xgetlist()
1503  call assert_equal(2, len(l))
1504  call assert_equal(2, l[1].lnum)
1505
1506  Xnext
1507  call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 3}], 'a')
1508  let l = g:Xgetlist()
1509  call assert_equal(3, len(l))
1510  Xnext
1511  call assert_equal(3, line('.'))
1512
1513  " Appending entries to the list should not change the cursor position
1514  " in the quickfix window
1515  Xwindow
1516  1
1517  call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 4},
1518	      \  {'bufnr': a:bnum, 'lnum': 5}], 'a')
1519  call assert_equal(1, line('.'))
1520  close
1521
1522  call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 3},
1523	      \  {'bufnr': a:bnum, 'lnum': 4},
1524	      \  {'bufnr': a:bnum, 'lnum': 5}], 'r')
1525  let l = g:Xgetlist()
1526  call assert_equal(3, len(l))
1527  call assert_equal(5, l[2].lnum)
1528
1529  call g:Xsetlist([])
1530  let l = g:Xgetlist()
1531  call assert_equal(0, len(l))
1532
1533  " Tests for setting the 'valid' flag
1534  call g:Xsetlist([{'bufnr':a:bnum, 'lnum':4, 'valid':0}])
1535  Xwindow
1536  call assert_equal(1, winnr('$'))
1537  let l = g:Xgetlist()
1538  call g:Xsetlist(l)
1539  call assert_equal(0, g:Xgetlist()[0].valid)
1540  " Adding a non-valid entry should not mark the list as having valid entries
1541  call g:Xsetlist([{'bufnr':a:bnum, 'lnum':5, 'valid':0}], 'a')
1542  Xwindow
1543  call assert_equal(1, winnr('$'))
1544
1545  " :cnext/:cprev should still work even with invalid entries in the list
1546  let l = [{'bufnr' : a:bnum, 'lnum' : 1, 'text' : '1', 'valid' : 0},
1547	      \ {'bufnr' : a:bnum, 'lnum' : 2, 'text' : '2', 'valid' : 0}]
1548  call g:Xsetlist(l)
1549  Xnext
1550  call assert_equal(2, g:Xgetlist({'idx' : 0}).idx)
1551  Xprev
1552  call assert_equal(1, g:Xgetlist({'idx' : 0}).idx)
1553  " :cnext/:cprev should still work after appending invalid entries to an
1554  " empty list
1555  call g:Xsetlist([])
1556  call g:Xsetlist(l, 'a')
1557  Xnext
1558  call assert_equal(2, g:Xgetlist({'idx' : 0}).idx)
1559  Xprev
1560  call assert_equal(1, g:Xgetlist({'idx' : 0}).idx)
1561
1562  call g:Xsetlist([{'text':'Text1', 'valid':1}])
1563  Xwindow
1564  call assert_equal(2, winnr('$'))
1565  Xclose
1566  let save_efm = &efm
1567  set efm=%m
1568  Xgetexpr 'TestMessage'
1569  let l = g:Xgetlist()
1570  call g:Xsetlist(l)
1571  call assert_equal(1, g:Xgetlist()[0].valid)
1572  let &efm = save_efm
1573
1574  " Error cases:
1575  " Refer to a non-existing buffer and pass a non-dictionary type
1576  call assert_fails("call g:Xsetlist([{'bufnr':998, 'lnum':4}," .
1577	      \ " {'bufnr':999, 'lnum':5}])", 'E92:')
1578  call g:Xsetlist([[1, 2,3]])
1579  call assert_equal(0, len(g:Xgetlist()))
1580  call assert_fails('call g:Xsetlist([], [])', 'E928:')
1581endfunc
1582
1583func Test_setqflist()
1584  new Xtestfile | only
1585  let bnum = bufnr('%')
1586  call setline(1, range(1,5))
1587
1588  call SetXlistTests('c', bnum)
1589  call SetXlistTests('l', bnum)
1590
1591  enew!
1592  call delete('Xtestfile')
1593endfunc
1594
1595func Xlist_empty_middle(cchar)
1596  call s:setup_commands(a:cchar)
1597
1598  " create three quickfix lists
1599  let @/ = 'Test_'
1600  Xvimgrep // test_quickfix.vim
1601  let testlen = len(g:Xgetlist())
1602  call assert_true(testlen > 0)
1603  Xvimgrep empty test_quickfix.vim
1604  call assert_true(len(g:Xgetlist()) > 0)
1605  Xvimgrep matches test_quickfix.vim
1606  let matchlen = len(g:Xgetlist())
1607  call assert_true(matchlen > 0)
1608  Xolder
1609  " make the middle list empty
1610  call g:Xsetlist([], 'r')
1611  call assert_true(len(g:Xgetlist()) == 0)
1612  Xolder
1613  call assert_equal(testlen, len(g:Xgetlist()))
1614  Xnewer
1615  Xnewer
1616  call assert_equal(matchlen, len(g:Xgetlist()))
1617endfunc
1618
1619func Test_setqflist_empty_middle()
1620  call Xlist_empty_middle('c')
1621  call Xlist_empty_middle('l')
1622endfunc
1623
1624func Xlist_empty_older(cchar)
1625  call s:setup_commands(a:cchar)
1626
1627  " create three quickfix lists
1628  Xvimgrep one test_quickfix.vim
1629  let onelen = len(g:Xgetlist())
1630  call assert_true(onelen > 0)
1631  Xvimgrep two test_quickfix.vim
1632  let twolen = len(g:Xgetlist())
1633  call assert_true(twolen > 0)
1634  Xvimgrep three test_quickfix.vim
1635  let threelen = len(g:Xgetlist())
1636  call assert_true(threelen > 0)
1637  Xolder 2
1638  " make the first list empty, check the others didn't change
1639  call g:Xsetlist([], 'r')
1640  call assert_true(len(g:Xgetlist()) == 0)
1641  Xnewer
1642  call assert_equal(twolen, len(g:Xgetlist()))
1643  Xnewer
1644  call assert_equal(threelen, len(g:Xgetlist()))
1645endfunc
1646
1647func Test_setqflist_empty_older()
1648  call Xlist_empty_older('c')
1649  call Xlist_empty_older('l')
1650endfunc
1651
1652func XquickfixSetListWithAct(cchar)
1653  call s:setup_commands(a:cchar)
1654
1655  let list1 = [{'filename': 'fnameA', 'text': 'A'},
1656          \    {'filename': 'fnameB', 'text': 'B'}]
1657  let list2 = [{'filename': 'fnameC', 'text': 'C'},
1658          \    {'filename': 'fnameD', 'text': 'D'},
1659          \    {'filename': 'fnameE', 'text': 'E'}]
1660
1661  " {action} is unspecified.  Same as specifying ' '.
1662  new | only
1663  silent! Xnewer 99
1664  call g:Xsetlist(list1)
1665  call g:Xsetlist(list2)
1666  let li = g:Xgetlist()
1667  call assert_equal(3, len(li))
1668  call assert_equal('C', li[0]['text'])
1669  call assert_equal('D', li[1]['text'])
1670  call assert_equal('E', li[2]['text'])
1671  silent! Xolder
1672  let li = g:Xgetlist()
1673  call assert_equal(2, len(li))
1674  call assert_equal('A', li[0]['text'])
1675  call assert_equal('B', li[1]['text'])
1676
1677  " {action} is specified ' '.
1678  new | only
1679  silent! Xnewer 99
1680  call g:Xsetlist(list1)
1681  call g:Xsetlist(list2, ' ')
1682  let li = g:Xgetlist()
1683  call assert_equal(3, len(li))
1684  call assert_equal('C', li[0]['text'])
1685  call assert_equal('D', li[1]['text'])
1686  call assert_equal('E', li[2]['text'])
1687  silent! Xolder
1688  let li = g:Xgetlist()
1689  call assert_equal(2, len(li))
1690  call assert_equal('A', li[0]['text'])
1691  call assert_equal('B', li[1]['text'])
1692
1693  " {action} is specified 'a'.
1694  new | only
1695  silent! Xnewer 99
1696  call g:Xsetlist(list1)
1697  call g:Xsetlist(list2, 'a')
1698  let li = g:Xgetlist()
1699  call assert_equal(5, len(li))
1700  call assert_equal('A', li[0]['text'])
1701  call assert_equal('B', li[1]['text'])
1702  call assert_equal('C', li[2]['text'])
1703  call assert_equal('D', li[3]['text'])
1704  call assert_equal('E', li[4]['text'])
1705
1706  " {action} is specified 'r'.
1707  new | only
1708  silent! Xnewer 99
1709  call g:Xsetlist(list1)
1710  call g:Xsetlist(list2, 'r')
1711  let li = g:Xgetlist()
1712  call assert_equal(3, len(li))
1713  call assert_equal('C', li[0]['text'])
1714  call assert_equal('D', li[1]['text'])
1715  call assert_equal('E', li[2]['text'])
1716
1717  " Test for wrong value.
1718  new | only
1719  call assert_fails("call g:Xsetlist(0)", 'E714:')
1720  call assert_fails("call g:Xsetlist(list1, '')", 'E927:')
1721  call assert_fails("call g:Xsetlist(list1, 'aa')", 'E927:')
1722  call assert_fails("call g:Xsetlist(list1, ' a')", 'E927:')
1723  call assert_fails("call g:Xsetlist(list1, 0)", 'E928:')
1724endfunc
1725
1726func Test_setqflist_invalid_nr()
1727  " The following command used to crash Vim
1728  eval []->setqflist(' ', {'nr' : $XXX_DOES_NOT_EXIST})
1729endfunc
1730
1731func Test_setqflist_user_sets_buftype()
1732  call setqflist([{'text': 'foo'}, {'text': 'bar'}])
1733  set buftype=quickfix
1734  call setqflist([], 'a')
1735  enew
1736endfunc
1737
1738func Test_quickfix_set_list_with_act()
1739  call XquickfixSetListWithAct('c')
1740  call XquickfixSetListWithAct('l')
1741endfunc
1742
1743func XLongLinesTests(cchar)
1744  let l = g:Xgetlist()
1745
1746  call assert_equal(4, len(l))
1747  call assert_equal(1, l[0].lnum)
1748  call assert_equal(1, l[0].col)
1749  call assert_equal(1975, len(l[0].text))
1750  call assert_equal(2, l[1].lnum)
1751  call assert_equal(1, l[1].col)
1752  call assert_equal(4070, len(l[1].text))
1753  call assert_equal(3, l[2].lnum)
1754  call assert_equal(1, l[2].col)
1755  call assert_equal(4070, len(l[2].text))
1756  call assert_equal(4, l[3].lnum)
1757  call assert_equal(1, l[3].col)
1758  call assert_equal(10, len(l[3].text))
1759
1760  call g:Xsetlist([], 'r')
1761endfunc
1762
1763func s:long_lines_tests(cchar)
1764  call s:setup_commands(a:cchar)
1765
1766  let testfile = 'samples/quickfix.txt'
1767
1768  " file
1769  exe 'Xgetfile' testfile
1770  call XLongLinesTests(a:cchar)
1771
1772  " list
1773  Xexpr readfile(testfile)
1774  call XLongLinesTests(a:cchar)
1775
1776  " string
1777  Xexpr join(readfile(testfile), "\n")
1778  call XLongLinesTests(a:cchar)
1779
1780  " buffer
1781  exe 'edit' testfile
1782  exe 'Xbuffer' bufnr('%')
1783  call XLongLinesTests(a:cchar)
1784endfunc
1785
1786func Test_long_lines()
1787  call s:long_lines_tests('c')
1788  call s:long_lines_tests('l')
1789endfunc
1790
1791func Test_cgetfile_on_long_lines()
1792  " Problematic values if the line is longer than 4096 bytes.  Then 1024 bytes
1793  " are read at a time.
1794  for len in [4078, 4079, 4080, 5102, 5103, 5104, 6126, 6127, 6128, 7150, 7151, 7152]
1795    let lines = [
1796      \ '/tmp/file1:1:1:aaa',
1797      \ '/tmp/file2:1:1:%s',
1798      \ '/tmp/file3:1:1:bbb',
1799      \ '/tmp/file4:1:1:ccc',
1800      \ ]
1801    let lines[1] = substitute(lines[1], '%s', repeat('x', len), '')
1802    call writefile(lines, 'Xcqetfile.txt')
1803    cgetfile Xcqetfile.txt
1804    call assert_equal(4, getqflist(#{size: v:true}).size, 'with length ' .. len)
1805  endfor
1806  call delete('Xcqetfile.txt')
1807endfunc
1808
1809func s:create_test_file(filename)
1810  let l = []
1811  for i in range(1, 20)
1812      call add(l, 'Line' . i)
1813  endfor
1814  call writefile(l, a:filename)
1815endfunc
1816
1817func Test_switchbuf()
1818  call s:create_test_file('Xqftestfile1')
1819  call s:create_test_file('Xqftestfile2')
1820  call s:create_test_file('Xqftestfile3')
1821
1822  new | only
1823  edit Xqftestfile1
1824  let file1_winid = win_getid()
1825  new Xqftestfile2
1826  let file2_winid = win_getid()
1827  cgetexpr ['Xqftestfile1:5:Line5',
1828		\ 'Xqftestfile1:6:Line6',
1829		\ 'Xqftestfile2:10:Line10',
1830		\ 'Xqftestfile2:11:Line11',
1831		\ 'Xqftestfile3:15:Line15',
1832		\ 'Xqftestfile3:16:Line16']
1833
1834  new
1835  let winid = win_getid()
1836  cfirst | cnext
1837  call assert_equal(winid, win_getid())
1838  2cnext
1839  call assert_equal(winid, win_getid())
1840  2cnext
1841  call assert_equal(winid, win_getid())
1842
1843  " Test for 'switchbuf' set to search for files in windows in the current
1844  " tabpage and jump to an existing window (if present)
1845  set switchbuf=useopen
1846  enew
1847  cfirst | cnext
1848  call assert_equal(file1_winid, win_getid())
1849  2cnext
1850  call assert_equal(file2_winid, win_getid())
1851  2cnext
1852  call assert_equal(file2_winid, win_getid())
1853
1854  " Test for 'switchbuf' set to search for files in tabpages and jump to an
1855  " existing tabpage (if present)
1856  enew | only
1857  set switchbuf=usetab
1858  tabedit Xqftestfile1
1859  tabedit Xqftestfile2
1860  tabedit Xqftestfile3
1861  tabfirst
1862  cfirst | cnext
1863  call assert_equal(2, tabpagenr())
1864  2cnext
1865  call assert_equal(3, tabpagenr())
1866  6cnext
1867  call assert_equal(4, tabpagenr())
1868  2cpfile
1869  call assert_equal(2, tabpagenr())
1870  2cnfile
1871  call assert_equal(4, tabpagenr())
1872  tabfirst | tabonly | enew
1873
1874  " Test for 'switchbuf' set to open a new window for every file
1875  set switchbuf=split
1876  cfirst | cnext
1877  call assert_equal(1, winnr('$'))
1878  cnext | cnext
1879  call assert_equal(2, winnr('$'))
1880  cnext | cnext
1881  call assert_equal(3, winnr('$'))
1882
1883  " Test for 'switchbuf' set to open a new tabpage for every file
1884  set switchbuf=newtab
1885  enew | only
1886  cfirst | cnext
1887  call assert_equal(1, tabpagenr('$'))
1888  cnext | cnext
1889  call assert_equal(2, tabpagenr('$'))
1890  cnext | cnext
1891  call assert_equal(3, tabpagenr('$'))
1892  tabfirst | enew | tabonly | only
1893
1894  set switchbuf=uselast
1895  split
1896  let last_winid = win_getid()
1897  copen
1898  exe "normal 1G\<CR>"
1899  call assert_equal(last_winid, win_getid())
1900  enew | only
1901
1902  " With an empty 'switchbuf', jumping to a quickfix entry should open the
1903  " file in an existing window (if present)
1904  set switchbuf=
1905  edit Xqftestfile1
1906  let file1_winid = win_getid()
1907  new Xqftestfile2
1908  let file2_winid = win_getid()
1909  copen
1910  exe "normal 1G\<CR>"
1911  call assert_equal(file1_winid, win_getid())
1912  copen
1913  exe "normal 3G\<CR>"
1914  call assert_equal(file2_winid, win_getid())
1915  copen | only
1916  exe "normal 5G\<CR>"
1917  call assert_equal(2, winnr('$'))
1918  call assert_equal(1, bufwinnr('Xqftestfile3'))
1919
1920  " If only quickfix window is open in the current tabpage, jumping to an
1921  " entry with 'switchbuf' set to 'usetab' should search in other tabpages.
1922  enew | only
1923  set switchbuf=usetab
1924  tabedit Xqftestfile1
1925  tabedit Xqftestfile2
1926  tabedit Xqftestfile3
1927  tabfirst
1928  copen | only
1929  clast
1930  call assert_equal(4, tabpagenr())
1931  tabfirst | tabonly | enew | only
1932
1933  " Jumping to a file that is not present in any of the tabpages and the
1934  " current tabpage doesn't have any usable windows, should open it in a new
1935  " window in the current tabpage.
1936  copen | only
1937  cfirst
1938  call assert_equal(1, tabpagenr())
1939  call assert_equal('Xqftestfile1', @%)
1940
1941  " If opening a file changes 'switchbuf', then the new value should be
1942  " retained.
1943  set modeline&vim
1944  call writefile(["vim: switchbuf=split"], 'Xqftestfile1')
1945  enew | only
1946  set switchbuf&vim
1947  cexpr "Xqftestfile1:1:10"
1948  call assert_equal('split', &switchbuf)
1949  call writefile(["vim: switchbuf=usetab"], 'Xqftestfile1')
1950  enew | only
1951  set switchbuf=useopen
1952  cexpr "Xqftestfile1:1:10"
1953  call assert_equal('usetab', &switchbuf)
1954  call writefile(["vim: switchbuf&vim"], 'Xqftestfile1')
1955  enew | only
1956  set switchbuf=useopen
1957  cexpr "Xqftestfile1:1:10"
1958  call assert_equal('', &switchbuf)
1959
1960  call delete('Xqftestfile1')
1961  call delete('Xqftestfile2')
1962  call delete('Xqftestfile3')
1963  set switchbuf&vim
1964
1965  enew | only
1966endfunc
1967
1968func Xadjust_qflnum(cchar)
1969  call s:setup_commands(a:cchar)
1970
1971  enew | only
1972
1973  let fname = 'Xqftestfile' . a:cchar
1974  call s:create_test_file(fname)
1975  exe 'edit ' . fname
1976
1977  Xgetexpr [fname . ':5:Line5',
1978	      \ fname . ':10:Line10',
1979	      \ fname . ':15:Line15',
1980	      \ fname . ':20:Line20']
1981
1982  6,14delete
1983  call append(6, ['Buffer', 'Window'])
1984
1985  let l = g:Xgetlist()
1986  call assert_equal(5, l[0].lnum)
1987  call assert_equal(6, l[2].lnum)
1988  call assert_equal(13, l[3].lnum)
1989
1990  " If a file doesn't have any quickfix entries, then deleting lines in the
1991  " file should not update the quickfix list
1992  call g:Xsetlist([], 'f')
1993  1,2delete
1994  call assert_equal([], g:Xgetlist())
1995
1996  enew!
1997  call delete(fname)
1998endfunc
1999
2000func Test_adjust_lnum()
2001  call setloclist(0, [])
2002  call Xadjust_qflnum('c')
2003  call setqflist([])
2004  call Xadjust_qflnum('l')
2005endfunc
2006
2007" Tests for the :grep/:lgrep and :grepadd/:lgrepadd commands
2008func s:test_xgrep(cchar)
2009  call s:setup_commands(a:cchar)
2010
2011  " The following lines are used for the grep test. Don't remove.
2012  " Grep_Test_Text: Match 1
2013  " Grep_Test_Text: Match 2
2014  " GrepAdd_Test_Text: Match 1
2015  " GrepAdd_Test_Text: Match 2
2016  enew! | only
2017  set makeef&vim
2018  silent Xgrep Grep_Test_Text: test_quickfix.vim
2019  call assert_true(len(g:Xgetlist()) == 5)
2020  Xopen
2021  call assert_true(w:quickfix_title =~ '^:grep')
2022  Xclose
2023  enew
2024  set makeef=Temp_File_##
2025  silent Xgrepadd GrepAdd_Test_Text: test_quickfix.vim
2026  call assert_true(len(g:Xgetlist()) == 9)
2027
2028  " Try with 'grepprg' set to 'internal'
2029  set grepprg=internal
2030  silent Xgrep Grep_Test_Text: test_quickfix.vim
2031  silent Xgrepadd GrepAdd_Test_Text: test_quickfix.vim
2032  call assert_true(len(g:Xgetlist()) == 9)
2033  set grepprg&vim
2034
2035  call writefile(['Vim'], 'XtestTempFile')
2036  set makeef=XtestTempFile
2037  silent Xgrep Grep_Test_Text: test_quickfix.vim
2038  call assert_equal(5, len(g:Xgetlist()))
2039  call assert_false(filereadable('XtestTempFile'))
2040  set makeef&vim
2041endfunc
2042
2043func Test_grep()
2044  " The grepprg may not be set on non-Unix systems
2045  CheckUnix
2046
2047  call s:test_xgrep('c')
2048  call s:test_xgrep('l')
2049endfunc
2050
2051func Test_two_windows()
2052  " Use one 'errorformat' for two windows.  Add an expression to each of them,
2053  " make sure they each keep their own state.
2054  set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f'
2055  call mkdir('Xone/a', 'p')
2056  call mkdir('Xtwo/a', 'p')
2057  let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7']
2058  call writefile(lines, 'Xone/a/one.txt')
2059  call writefile(lines, 'Xtwo/a/two.txt')
2060
2061  new one
2062  let one_id = win_getid()
2063  lexpr ""
2064  new two
2065  let two_id = win_getid()
2066  lexpr ""
2067
2068  laddexpr "Entering dir 'Xtwo/a'"
2069  call win_gotoid(one_id)
2070  laddexpr "Entering dir 'Xone/a'"
2071  call win_gotoid(two_id)
2072  laddexpr 'two.txt:5:two two two'
2073  call win_gotoid(one_id)
2074  laddexpr 'one.txt:3:one one one'
2075
2076  let loc_one = getloclist(one_id)
2077  call assert_equal('Xone/a/one.txt', bufname(loc_one[1].bufnr))
2078  call assert_equal(3, loc_one[1].lnum)
2079
2080  let loc_two = getloclist(two_id)
2081  call assert_equal('Xtwo/a/two.txt', bufname(loc_two[1].bufnr))
2082  call assert_equal(5, loc_two[1].lnum)
2083
2084  call win_gotoid(one_id)
2085  bwipe!
2086  call win_gotoid(two_id)
2087  bwipe!
2088  call delete('Xone', 'rf')
2089  call delete('Xtwo', 'rf')
2090endfunc
2091
2092func XbottomTests(cchar)
2093  call s:setup_commands(a:cchar)
2094
2095  " Calling lbottom without any errors should fail
2096  if a:cchar == 'l'
2097      call assert_fails('lbottom', 'E776:')
2098  endif
2099
2100  call g:Xsetlist([{'filename': 'foo', 'lnum': 42}])
2101  Xopen
2102  let wid = win_getid()
2103  call assert_equal(1, line('.'))
2104  wincmd w
2105  call g:Xsetlist([{'filename': 'var', 'lnum': 24}], 'a')
2106  Xbottom
2107  call win_gotoid(wid)
2108  call assert_equal(2, line('.'))
2109  Xclose
2110endfunc
2111
2112" Tests for the :cbottom and :lbottom commands
2113func Test_cbottom()
2114  call XbottomTests('c')
2115  call XbottomTests('l')
2116endfunc
2117
2118func HistoryTest(cchar)
2119  call s:setup_commands(a:cchar)
2120
2121  " clear all lists after the first one, then replace the first one.
2122  call g:Xsetlist([])
2123  call assert_fails('Xolder 99', 'E380:')
2124  let entry = {'filename': 'foo', 'lnum': 42}
2125  call g:Xsetlist([entry], 'r')
2126  call g:Xsetlist([entry, entry])
2127  call g:Xsetlist([entry, entry, entry])
2128  let res = split(execute(a:cchar . 'hist'), "\n")
2129  call assert_equal(3, len(res))
2130  let common = 'errors     :set' . (a:cchar == 'c' ? 'qf' : 'loc') . 'list()'
2131  call assert_equal('  error list 1 of 3; 1 ' . common, res[0])
2132  call assert_equal('  error list 2 of 3; 2 ' . common, res[1])
2133  call assert_equal('> error list 3 of 3; 3 ' . common, res[2])
2134
2135  " Test for changing the quickfix lists
2136  call assert_equal(3, g:Xgetlist({'nr' : 0}).nr)
2137  exe '1' . a:cchar . 'hist'
2138  call assert_equal(1, g:Xgetlist({'nr' : 0}).nr)
2139  exe '3' . a:cchar . 'hist'
2140  call assert_equal(3, g:Xgetlist({'nr' : 0}).nr)
2141  call assert_fails('-2' . a:cchar . 'hist', 'E16:')
2142  call assert_fails('4' . a:cchar . 'hist', 'E16:')
2143
2144  call g:Xsetlist([], 'f')
2145  let l = split(execute(a:cchar . 'hist'), "\n")
2146  call assert_equal('No entries', l[0])
2147  if a:cchar == 'c'
2148    call assert_fails('4chist', 'E16:')
2149  else
2150    call assert_fails('4lhist', 'E776:')
2151  endif
2152
2153  " An empty list should still show the stack history
2154  call g:Xsetlist([])
2155  let res = split(execute(a:cchar . 'hist'), "\n")
2156  call assert_equal('> error list 1 of 1; 0 ' . common, res[0])
2157
2158  call g:Xsetlist([], 'f')
2159endfunc
2160
2161func Test_history()
2162  call HistoryTest('c')
2163  call HistoryTest('l')
2164endfunc
2165
2166func Test_duplicate_buf()
2167  " make sure we can get the highest buffer number
2168  edit DoesNotExist
2169  edit DoesNotExist2
2170  let last_buffer = bufnr("$")
2171
2172  " make sure only one buffer is created
2173  call writefile(['this one', 'that one'], 'Xgrepthis')
2174  vimgrep one Xgrepthis
2175  vimgrep one Xgrepthis
2176  call assert_equal(last_buffer + 1, bufnr("$"))
2177
2178  call delete('Xgrepthis')
2179endfunc
2180
2181" Quickfix/Location list set/get properties tests
2182func Xproperty_tests(cchar)
2183  call s:setup_commands(a:cchar)
2184
2185  " Error cases
2186  call assert_fails('call g:Xgetlist(99)', 'E715:')
2187  call assert_fails('call g:Xsetlist(99)', 'E714:')
2188  call assert_fails('call g:Xsetlist([], "a", [])', 'E715:')
2189
2190  " Set and get the title
2191  call g:Xsetlist([])
2192  Xopen
2193  wincmd p
2194  call g:Xsetlist([{'filename':'foo', 'lnum':27}])
2195  let s = g:Xsetlist([], 'a', {'title' : 'Sample'})
2196  call assert_equal(0, s)
2197  let d = g:Xgetlist({"title":1})
2198  call assert_equal('Sample', d.title)
2199  " Try setting title to a non-string value
2200  call assert_equal(-1, g:Xsetlist([], 'a', {'title' : ['Test']}))
2201  call assert_equal('Sample', g:Xgetlist({"title":1}).title)
2202
2203  Xopen
2204  call assert_equal('Sample', w:quickfix_title)
2205  Xclose
2206
2207  " Tests for action argument
2208  silent! Xolder 999
2209  let qfnr = g:Xgetlist({'all':1}).nr
2210  call g:Xsetlist([], 'r', {'title' : 'N1'})
2211  call assert_equal('N1', g:Xgetlist({'all':1}).title)
2212  call g:Xsetlist([], ' ', {'title' : 'N2'})
2213  call assert_equal(qfnr + 1, g:Xgetlist({'all':1}).nr)
2214
2215  let res = g:Xgetlist({'nr': 0})
2216  call assert_equal(qfnr + 1, res.nr)
2217  call assert_equal(['nr'], keys(res))
2218
2219  call g:Xsetlist([], ' ', {'title' : 'N3'})
2220  call assert_equal('N2', g:Xgetlist({'nr':2, 'title':1}).title)
2221
2222  " Changing the title of an earlier quickfix list
2223  call g:Xsetlist([], 'r', {'title' : 'NewTitle', 'nr' : 2})
2224  call assert_equal('NewTitle', g:Xgetlist({'nr':2, 'title':1}).title)
2225
2226  " Changing the title of an invalid quickfix list
2227  call assert_equal(-1, g:Xsetlist([], ' ',
2228        \ {'title' : 'SomeTitle', 'nr' : 99}))
2229  call assert_equal(-1, g:Xsetlist([], ' ',
2230        \ {'title' : 'SomeTitle', 'nr' : 'abc'}))
2231
2232  if a:cchar == 'c'
2233    copen
2234    call assert_equal({'winid':win_getid()}, getqflist({'winid':1}))
2235    cclose
2236  endif
2237
2238  " Invalid arguments
2239  call assert_fails('call g:Xgetlist([])', 'E715:')
2240  call assert_fails('call g:Xsetlist([], "a", [])', 'E715:')
2241  let s = g:Xsetlist([], 'a', {'abc':1})
2242  call assert_equal(-1, s)
2243
2244  call assert_equal({}, g:Xgetlist({'abc':1}))
2245  call assert_equal('', g:Xgetlist({'nr':99, 'title':1}).title)
2246  call assert_equal('', g:Xgetlist({'nr':[], 'title':1}).title)
2247
2248  if a:cchar == 'l'
2249    call assert_equal({}, getloclist(99, {'title': 1}))
2250  endif
2251
2252  " Context related tests
2253  let s = g:Xsetlist([], 'a', {'context':[1,2,3]})
2254  call assert_equal(0, s)
2255  call test_garbagecollect_now()
2256  let d = g:Xgetlist({'context':1})
2257  call assert_equal([1,2,3], d.context)
2258  call g:Xsetlist([], 'a', {'context':{'color':'green'}})
2259  let d = g:Xgetlist({'context':1})
2260  call assert_equal({'color':'green'}, d.context)
2261  call g:Xsetlist([], 'a', {'context':"Context info"})
2262  let d = g:Xgetlist({'context':1})
2263  call assert_equal("Context info", d.context)
2264  call g:Xsetlist([], 'a', {'context':246})
2265  let d = g:Xgetlist({'context':1})
2266  call assert_equal(246, d.context)
2267  " set other Vim data types as context
2268  call g:Xsetlist([], 'a', {'context' : test_null_blob()})
2269  if has('channel')
2270    call g:Xsetlist([], 'a', {'context' : test_null_channel()})
2271  endif
2272  if has('job')
2273    call g:Xsetlist([], 'a', {'context' : test_null_job()})
2274  endif
2275  call g:Xsetlist([], 'a', {'context' : test_null_function()})
2276  call g:Xsetlist([], 'a', {'context' : test_null_partial()})
2277  call g:Xsetlist([], 'a', {'context' : ''})
2278  call test_garbagecollect_now()
2279  if a:cchar == 'l'
2280    " Test for copying context across two different location lists
2281    new | only
2282    let w1_id = win_getid()
2283    let l = [1]
2284    call setloclist(0, [], 'a', {'context':l})
2285    new
2286    let w2_id = win_getid()
2287    call add(l, 2)
2288    call assert_equal([1, 2], getloclist(w1_id, {'context':1}).context)
2289    call assert_equal([1, 2], getloclist(w2_id, {'context':1}).context)
2290    unlet! l
2291    call assert_equal([1, 2], getloclist(w2_id, {'context':1}).context)
2292    only
2293    call setloclist(0, [], 'f')
2294    call assert_equal('', getloclist(0, {'context':1}).context)
2295  endif
2296
2297  " Test for changing the context of previous quickfix lists
2298  call g:Xsetlist([], 'f')
2299  Xexpr "One"
2300  Xexpr "Two"
2301  Xexpr "Three"
2302  call g:Xsetlist([], 'r', {'context' : [1], 'nr' : 1})
2303  call g:Xsetlist([], 'a', {'context' : [2], 'nr' : 2})
2304  " Also, check for setting the context using quickfix list number zero.
2305  call g:Xsetlist([], 'r', {'context' : [3], 'nr' : 0})
2306  call test_garbagecollect_now()
2307  let l = g:Xgetlist({'nr' : 1, 'context' : 1})
2308  call assert_equal([1], l.context)
2309  let l = g:Xgetlist({'nr' : 2, 'context' : 1})
2310  call assert_equal([2], l.context)
2311  let l = g:Xgetlist({'nr' : 3, 'context' : 1})
2312  call assert_equal([3], l.context)
2313
2314  " Test for changing the context through reference and for garbage
2315  " collection of quickfix context
2316  let l = ["red"]
2317  call g:Xsetlist([], ' ', {'context' : l})
2318  call add(l, "blue")
2319  let x = g:Xgetlist({'context' : 1})
2320  call add(x.context, "green")
2321  call assert_equal(["red", "blue", "green"], l)
2322  call assert_equal(["red", "blue", "green"], x.context)
2323  unlet l
2324  call test_garbagecollect_now()
2325  let m = g:Xgetlist({'context' : 1})
2326  call assert_equal(["red", "blue", "green"], m.context)
2327
2328  " Test for setting/getting items
2329  Xexpr ""
2330  let qfprev = g:Xgetlist({'nr':0})
2331  let s = g:Xsetlist([], ' ', {'title':'Green',
2332        \ 'items' : [{'filename':'F1', 'lnum':10}]})
2333  call assert_equal(0, s)
2334  let qfcur = g:Xgetlist({'nr':0})
2335  call assert_true(qfcur.nr == qfprev.nr + 1)
2336  let l = g:Xgetlist({'items':1})
2337  call assert_equal('F1', bufname(l.items[0].bufnr))
2338  call assert_equal(10, l.items[0].lnum)
2339  call g:Xsetlist([], 'a', {'items' : [{'filename':'F2', 'lnum':20},
2340        \  {'filename':'F2', 'lnum':30}]})
2341  let l = g:Xgetlist({'items':1})
2342  call assert_equal('F2', bufname(l.items[2].bufnr))
2343  call assert_equal(30, l.items[2].lnum)
2344  call g:Xsetlist([], 'r', {'items' : [{'filename':'F3', 'lnum':40}]})
2345  let l = g:Xgetlist({'items':1})
2346  call assert_equal('F3', bufname(l.items[0].bufnr))
2347  call assert_equal(40, l.items[0].lnum)
2348  call g:Xsetlist([], 'r', {'items' : []})
2349  let l = g:Xgetlist({'items':1})
2350  call assert_equal(0, len(l.items))
2351
2352  call g:Xsetlist([], 'r', {'title' : 'TestTitle'})
2353  call g:Xsetlist([], 'r', {'items' : [{'filename' : 'F1', 'lnum' : 10, 'text' : 'L10'}]})
2354  call g:Xsetlist([], 'r', {'items' : [{'filename' : 'F1', 'lnum' : 10, 'text' : 'L10'}]})
2355  call assert_equal('TestTitle', g:Xgetlist({'title' : 1}).title)
2356
2357  " Test for getting id of window associated with a location list window
2358  if a:cchar == 'l'
2359    only
2360    call assert_equal(0, g:Xgetlist({'all' : 1}).filewinid)
2361    let wid = win_getid()
2362    Xopen
2363    call assert_equal(wid, g:Xgetlist({'filewinid' : 1}).filewinid)
2364    wincmd w
2365    call assert_equal(0, g:Xgetlist({'filewinid' : 1}).filewinid)
2366    only
2367  endif
2368
2369  " The following used to crash Vim with address sanitizer
2370  call g:Xsetlist([], 'f')
2371  call g:Xsetlist([], 'a', {'items' : [{'filename':'F1', 'lnum':10}]})
2372  call assert_equal(10, g:Xgetlist({'items':1}).items[0].lnum)
2373
2374  " Try setting the items using a string
2375  call assert_equal(-1, g:Xsetlist([], ' ', {'items' : 'Test'}))
2376
2377  " Save and restore the quickfix stack
2378  call g:Xsetlist([], 'f')
2379  call assert_equal(0, g:Xgetlist({'nr':'$'}).nr)
2380  Xexpr "File1:10:Line1"
2381  Xexpr "File2:20:Line2"
2382  Xexpr "File3:30:Line3"
2383  let last_qf = g:Xgetlist({'nr':'$'}).nr
2384  call assert_equal(3, last_qf)
2385  let qstack = []
2386  for i in range(1, last_qf)
2387    let qstack = add(qstack, g:Xgetlist({'nr':i, 'all':1}))
2388  endfor
2389  call g:Xsetlist([], 'f')
2390  for i in range(len(qstack))
2391    call g:Xsetlist([], ' ', qstack[i])
2392  endfor
2393  call assert_equal(3, g:Xgetlist({'nr':'$'}).nr)
2394  call assert_equal(10, g:Xgetlist({'nr':1, 'items':1}).items[0].lnum)
2395  call assert_equal(20, g:Xgetlist({'nr':2, 'items':1}).items[0].lnum)
2396  call assert_equal(30, g:Xgetlist({'nr':3, 'items':1}).items[0].lnum)
2397  call g:Xsetlist([], 'f')
2398
2399  " Swap two quickfix lists
2400  Xexpr "File1:10:Line10"
2401  Xexpr "File2:20:Line20"
2402  Xexpr "File3:30:Line30"
2403  call g:Xsetlist([], 'r', {'nr':1,'title':'Colors','context':['Colors']})
2404  call g:Xsetlist([], 'r', {'nr':2,'title':'Fruits','context':['Fruits']})
2405  let l1=g:Xgetlist({'nr':1,'all':1})
2406  let l2=g:Xgetlist({'nr':2,'all':1})
2407  let save_id = l1.id
2408  let l1.id=l2.id
2409  let l2.id=save_id
2410  call g:Xsetlist([], 'r', l1)
2411  call g:Xsetlist([], 'r', l2)
2412  let newl1=g:Xgetlist({'nr':1,'all':1})
2413  let newl2=g:Xgetlist({'nr':2,'all':1})
2414  call assert_equal('Fruits', newl1.title)
2415  call assert_equal(['Fruits'], newl1.context)
2416  call assert_equal('Line20', newl1.items[0].text)
2417  call assert_equal('Colors', newl2.title)
2418  call assert_equal(['Colors'], newl2.context)
2419  call assert_equal('Line10', newl2.items[0].text)
2420  call g:Xsetlist([], 'f')
2421
2422  " Cannot specify both a non-empty list argument and a dict argument
2423  call assert_fails("call g:Xsetlist([{}], ' ', {})", 'E475:')
2424endfunc
2425
2426func Test_qf_property()
2427  call Xproperty_tests('c')
2428  call Xproperty_tests('l')
2429endfunc
2430
2431" Test for setting the current index in the location/quickfix list
2432func Xtest_setqfidx(cchar)
2433  call s:setup_commands(a:cchar)
2434
2435  Xgetexpr "F1:10:1:Line1\nF2:20:2:Line2\nF3:30:3:Line3"
2436  Xgetexpr "F4:10:1:Line1\nF5:20:2:Line2\nF6:30:3:Line3"
2437  Xgetexpr "F7:10:1:Line1\nF8:20:2:Line2\nF9:30:3:Line3"
2438
2439  call g:Xsetlist([], 'a', {'nr' : 3, 'idx' : 2})
2440  call g:Xsetlist([], 'a', {'nr' : 2, 'idx' : 2})
2441  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 3})
2442  Xolder 2
2443  Xopen
2444  call assert_equal(3, line('.'))
2445  Xnewer
2446  call assert_equal(2, line('.'))
2447  Xnewer
2448  call assert_equal(2, line('.'))
2449  " Update the current index with the quickfix window open
2450  wincmd w
2451  call g:Xsetlist([], 'a', {'nr' : 3, 'idx' : 3})
2452  Xopen
2453  call assert_equal(3, line('.'))
2454  Xclose
2455
2456  " Set the current index to the last entry
2457  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : '$'})
2458  call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx)
2459  " A large value should set the index to the last index
2460  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 1})
2461  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 999})
2462  call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx)
2463  " Invalid index values
2464  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : -1})
2465  call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx)
2466  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 0})
2467  call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx)
2468  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 'xx'})
2469  call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx)
2470  call assert_fails("call g:Xsetlist([], 'a', {'nr':1, 'idx':[]})", 'E745:')
2471
2472  call g:Xsetlist([], 'f')
2473  new | only
2474endfunc
2475
2476func Test_setqfidx()
2477  call Xtest_setqfidx('c')
2478  call Xtest_setqfidx('l')
2479endfunc
2480
2481" Tests for the QuickFixCmdPre/QuickFixCmdPost autocommands
2482func QfAutoCmdHandler(loc, cmd)
2483  call add(g:acmds, a:loc . a:cmd)
2484endfunc
2485
2486func Test_Autocmd()
2487  autocmd QuickFixCmdPre * call QfAutoCmdHandler('pre', expand('<amatch>'))
2488  autocmd QuickFixCmdPost * call QfAutoCmdHandler('post', expand('<amatch>'))
2489
2490  let g:acmds = []
2491  cexpr "F1:10:Line 10"
2492  caddexpr "F1:20:Line 20"
2493  cgetexpr "F1:30:Line 30"
2494  cexpr ""
2495  caddexpr ""
2496  cgetexpr ""
2497  silent! cexpr non_existing_func()
2498  silent! caddexpr non_existing_func()
2499  silent! cgetexpr non_existing_func()
2500  let l = ['precexpr',
2501	      \ 'postcexpr',
2502	      \ 'precaddexpr',
2503	      \ 'postcaddexpr',
2504	      \ 'precgetexpr',
2505	      \ 'postcgetexpr',
2506	      \ 'precexpr',
2507	      \ 'postcexpr',
2508	      \ 'precaddexpr',
2509	      \ 'postcaddexpr',
2510	      \ 'precgetexpr',
2511	      \ 'postcgetexpr',
2512	      \ 'precexpr',
2513	      \ 'precaddexpr',
2514	      \ 'precgetexpr']
2515  call assert_equal(l, g:acmds)
2516
2517  let g:acmds = []
2518  enew! | call append(0, "F2:10:Line 10")
2519  cbuffer!
2520  enew! | call append(0, "F2:20:Line 20")
2521  cgetbuffer
2522  enew! | call append(0, "F2:30:Line 30")
2523  caddbuffer
2524  new
2525  let bnum = bufnr('%')
2526  bunload
2527  exe 'silent! cbuffer! ' . bnum
2528  exe 'silent! cgetbuffer ' . bnum
2529  exe 'silent! caddbuffer ' . bnum
2530  enew!
2531  let l = ['precbuffer',
2532	      \ 'postcbuffer',
2533	      \ 'precgetbuffer',
2534	      \ 'postcgetbuffer',
2535	      \ 'precaddbuffer',
2536	      \ 'postcaddbuffer',
2537	      \ 'precbuffer',
2538	      \ 'precgetbuffer',
2539	      \ 'precaddbuffer']
2540  call assert_equal(l, g:acmds)
2541
2542  call writefile(['Xtest:1:Line1'], 'Xtest')
2543  call writefile([], 'Xempty')
2544  let g:acmds = []
2545  cfile Xtest
2546  caddfile Xtest
2547  cgetfile Xtest
2548  cfile Xempty
2549  caddfile Xempty
2550  cgetfile Xempty
2551  silent! cfile do_not_exist
2552  silent! caddfile do_not_exist
2553  silent! cgetfile do_not_exist
2554  let l = ['precfile',
2555	      \ 'postcfile',
2556	      \ 'precaddfile',
2557	      \ 'postcaddfile',
2558	      \ 'precgetfile',
2559	      \ 'postcgetfile',
2560	      \ 'precfile',
2561	      \ 'postcfile',
2562	      \ 'precaddfile',
2563	      \ 'postcaddfile',
2564	      \ 'precgetfile',
2565	      \ 'postcgetfile',
2566	      \ 'precfile',
2567	      \ 'postcfile',
2568	      \ 'precaddfile',
2569	      \ 'postcaddfile',
2570	      \ 'precgetfile',
2571	      \ 'postcgetfile']
2572  call assert_equal(l, g:acmds)
2573
2574  let g:acmds = []
2575  helpgrep quickfix
2576  silent! helpgrep non_existing_help_topic
2577  vimgrep test Xtest
2578  vimgrepadd test Xtest
2579  silent! vimgrep non_existing_test Xtest
2580  silent! vimgrepadd non_existing_test Xtest
2581  set makeprg=
2582  silent! make
2583  set makeprg&
2584  let l = ['prehelpgrep',
2585	      \ 'posthelpgrep',
2586	      \ 'prehelpgrep',
2587	      \ 'posthelpgrep',
2588	      \ 'previmgrep',
2589	      \ 'postvimgrep',
2590	      \ 'previmgrepadd',
2591	      \ 'postvimgrepadd',
2592	      \ 'previmgrep',
2593	      \ 'postvimgrep',
2594	      \ 'previmgrepadd',
2595	      \ 'postvimgrepadd',
2596	      \ 'premake',
2597	      \ 'postmake']
2598  call assert_equal(l, g:acmds)
2599
2600  if has('unix')
2601    " Run this test only on Unix-like systems. The grepprg may not be set on
2602    " non-Unix systems.
2603    " The following lines are used for the grep test. Don't remove.
2604    " Grep_Autocmd_Text: Match 1
2605    " GrepAdd_Autocmd_Text: Match 2
2606    let g:acmds = []
2607    silent grep Grep_Autocmd_Text test_quickfix.vim
2608    silent grepadd GrepAdd_Autocmd_Text test_quickfix.vim
2609    silent grep abc123def Xtest
2610    silent grepadd abc123def Xtest
2611    set grepprg=internal
2612    silent grep Grep_Autocmd_Text test_quickfix.vim
2613    silent grepadd GrepAdd_Autocmd_Text test_quickfix.vim
2614    silent lgrep Grep_Autocmd_Text test_quickfix.vim
2615    silent lgrepadd GrepAdd_Autocmd_Text test_quickfix.vim
2616    set grepprg&vim
2617    let l = ['pregrep',
2618		\ 'postgrep',
2619		\ 'pregrepadd',
2620		\ 'postgrepadd',
2621		\ 'pregrep',
2622		\ 'postgrep',
2623		\ 'pregrepadd',
2624		\ 'postgrepadd',
2625		\ 'pregrep',
2626		\ 'postgrep',
2627		\ 'pregrepadd',
2628		\ 'postgrepadd',
2629		\ 'prelgrep',
2630		\ 'postlgrep',
2631		\ 'prelgrepadd',
2632		\ 'postlgrepadd']
2633    call assert_equal(l, g:acmds)
2634  endif
2635
2636  call delete('Xtest')
2637  call delete('Xempty')
2638  au! QuickFixCmdPre
2639  au! QuickFixCmdPost
2640endfunc
2641
2642func Test_Autocmd_Exception()
2643  set efm=%m
2644  lgetexpr '?'
2645
2646  try
2647    call DoesNotExit()
2648  catch
2649    lgetexpr '1'
2650  finally
2651    lgetexpr '1'
2652  endtry
2653
2654  call assert_equal('1', getloclist(0)[0].text)
2655
2656  set efm&vim
2657endfunc
2658
2659func Test_caddbuffer_wrong()
2660  " This used to cause a memory access in freed memory.
2661  let save_efm = &efm
2662  set efm=%EEEE%m,%WWWW,%+CCCC%>%#,%GGGG%.#
2663  cgetexpr ['WWWW', 'EEEE', 'CCCC']
2664  let &efm = save_efm
2665  caddbuffer
2666  bwipe!
2667endfunc
2668
2669func Test_caddexpr_wrong()
2670  " This used to cause a memory access in freed memory.
2671  cbuffer
2672  cbuffer
2673  copen
2674  let save_efm = &efm
2675  set efm=%
2676  call assert_fails('caddexpr ""', 'E376:')
2677  let &efm = save_efm
2678endfunc
2679
2680func Test_dirstack_cleanup()
2681  " This used to cause a memory access in freed memory.
2682  let save_efm = &efm
2683  lexpr '0'
2684  lopen
2685  fun X(c)
2686    let save_efm=&efm
2687    set efm=%D%f
2688    if a:c == 'c'
2689      caddexpr '::'
2690    else
2691      laddexpr ':0:0'
2692    endif
2693    let &efm=save_efm
2694  endfun
2695  call X('c')
2696  call X('l')
2697  call setqflist([], 'r')
2698  caddbuffer
2699  let &efm = save_efm
2700endfunc
2701
2702" Tests for jumping to entries from the location list window and quickfix
2703" window
2704func Test_cwindow_jump()
2705  set efm=%f%%%l%%%m
2706  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2707  lopen | only
2708  lfirst
2709  call assert_true(winnr('$') == 2)
2710  call assert_true(winnr() == 1)
2711  " Location list for the new window should be set
2712  call assert_true(getloclist(0)[2].text == 'Line 30')
2713
2714  " Open a scratch buffer
2715  " Open a new window and create a location list
2716  " Open the location list window and close the other window
2717  " Jump to an entry.
2718  " Should create a new window and jump to the entry. The scratch buffer
2719  " should not be used.
2720  enew | only
2721  set buftype=nofile
2722  below new
2723  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2724  lopen
2725  2wincmd c
2726  lnext
2727  call assert_true(winnr('$') == 3)
2728  call assert_true(winnr() == 2)
2729
2730  " Open two windows with two different location lists
2731  " Open the location list window and close the previous window
2732  " Jump to an entry in the location list window
2733  " Should open the file in the first window and not set the location list.
2734  enew | only
2735  lgetexpr ["F1%5%Line 5"]
2736  below new
2737  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2738  lopen
2739  2wincmd c
2740  lnext
2741  call assert_true(winnr() == 1)
2742  call assert_true(getloclist(0)[0].text == 'Line 5')
2743
2744  enew | only
2745  cgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2746  copen
2747  cnext
2748  call assert_true(winnr('$') == 2)
2749  call assert_true(winnr() == 1)
2750
2751  " open the quickfix buffer in two windows and jump to an entry. Should open
2752  " the file in the first quickfix window.
2753  enew | only
2754  copen
2755  let bnum = bufnr('')
2756  exe 'sbuffer ' . bnum
2757  wincmd b
2758  cfirst
2759  call assert_equal(2, winnr())
2760  call assert_equal('F1', @%)
2761  enew | only
2762  exe 'sb' bnum
2763  exe 'botright sb' bnum
2764  wincmd t
2765  clast
2766  call assert_equal(2, winnr())
2767  call assert_equal('quickfix', getwinvar(1, '&buftype'))
2768  call assert_equal('quickfix', getwinvar(3, '&buftype'))
2769
2770  " Jumping to a file from the location list window should find a usable
2771  " window by wrapping around the window list.
2772  enew | only
2773  call setloclist(0, [], 'f')
2774  new | new
2775  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2776  lopen
2777  1close
2778  call assert_equal(0, getloclist(3, {'id' : 0}).id)
2779  lnext
2780  call assert_equal(3, winnr())
2781  call assert_equal(getloclist(1, {'id' : 0}).id, getloclist(3, {'id' : 0}).id)
2782
2783  enew | only
2784  set efm&vim
2785endfunc
2786
2787func Test_cwindow_highlight()
2788  CheckScreendump
2789
2790  let lines =<< trim END
2791	call setline(1, ['some', 'text', 'with', 'matches'])
2792	write XCwindow
2793	vimgrep e XCwindow
2794	redraw
2795	cwindow 4
2796  END
2797  call writefile(lines, 'XtestCwindow')
2798  let buf = RunVimInTerminal('-S XtestCwindow', #{rows: 12})
2799  call VerifyScreenDump(buf, 'Test_quickfix_cwindow_1', {})
2800
2801  call term_sendkeys(buf, ":cnext\<CR>")
2802  call VerifyScreenDump(buf, 'Test_quickfix_cwindow_2', {})
2803
2804  " clean up
2805  call StopVimInTerminal(buf)
2806  call delete('XtestCwindow')
2807  call delete('XCwindow')
2808endfunc
2809
2810func XvimgrepTests(cchar)
2811  call s:setup_commands(a:cchar)
2812
2813  call writefile(['Editor:VIM vim',
2814	      \ 'Editor:Emacs EmAcS',
2815	      \ 'Editor:Notepad NOTEPAD'], 'Xtestfile1')
2816  call writefile(['Linux', 'MacOS', 'MS-Windows'], 'Xtestfile2')
2817
2818  " Error cases
2819  call assert_fails('Xvimgrep /abc *', 'E682:')
2820
2821  let @/=''
2822  call assert_fails('Xvimgrep // *', 'E35:')
2823
2824  call assert_fails('Xvimgrep abc', 'E683:')
2825  call assert_fails('Xvimgrep a1b2c3 Xtestfile1', 'E480:')
2826  call assert_fails('Xvimgrep pat Xa1b2c3', 'E480:')
2827
2828  Xexpr ""
2829  Xvimgrepadd Notepad Xtestfile1
2830  Xvimgrepadd MacOS Xtestfile2
2831  let l = g:Xgetlist()
2832  call assert_equal(2, len(l))
2833  call assert_equal('Editor:Notepad NOTEPAD', l[0].text)
2834
2835  10Xvimgrep #\cvim#g Xtestfile?
2836  let l = g:Xgetlist()
2837  call assert_equal(2, len(l))
2838  call assert_equal(8, l[0].col)
2839  call assert_equal(12, l[1].col)
2840
2841  1Xvimgrep ?Editor? Xtestfile*
2842  let l = g:Xgetlist()
2843  call assert_equal(1, len(l))
2844  call assert_equal('Editor:VIM vim', l[0].text)
2845
2846  edit +3 Xtestfile2
2847  Xvimgrep +\cemacs+j Xtestfile1
2848  let l = g:Xgetlist()
2849  call assert_equal('Xtestfile2', @%)
2850  call assert_equal('Editor:Emacs EmAcS', l[0].text)
2851
2852  " Test for unloading a buffer after vimgrep searched the buffer
2853  %bwipe
2854  Xvimgrep /Editor/j Xtestfile*
2855  call assert_equal(0, getbufinfo('Xtestfile1')[0].loaded)
2856  call assert_equal([], getbufinfo('Xtestfile2'))
2857
2858  call delete('Xtestfile1')
2859  call delete('Xtestfile2')
2860endfunc
2861
2862" Tests for the :vimgrep command
2863func Test_vimgrep()
2864  call XvimgrepTests('c')
2865  call XvimgrepTests('l')
2866endfunc
2867
2868func Test_vimgrep_wildcards_expanded_once()
2869  new X[id-01] file.txt
2870  call setline(1, 'some text to search for')
2871  vimgrep text %
2872  bwipe!
2873endfunc
2874
2875" Test for incsearch highlighting of the :vimgrep pattern
2876" This test used to cause "E315: ml_get: invalid lnum" errors.
2877func Test_vimgrep_incsearch()
2878  enew
2879  set incsearch
2880  call test_override("char_avail", 1)
2881
2882  call feedkeys(":2vimgrep assert test_quickfix.vim test_cdo.vim\<CR>", "ntx")
2883  let l = getqflist()
2884  call assert_equal(2, len(l))
2885
2886  call test_override("ALL", 0)
2887  set noincsearch
2888endfunc
2889
2890" Test vimgrep with the last search pattern not set
2891func Test_vimgrep_with_no_last_search_pat()
2892  let lines =<< trim [SCRIPT]
2893    call assert_fails('vimgrep // *', 'E35:')
2894    call writefile(v:errors, 'Xresult')
2895    qall!
2896  [SCRIPT]
2897  call writefile(lines, 'Xscript')
2898  if RunVim([], [], '--clean -S Xscript')
2899    call assert_equal([], readfile('Xresult'))
2900  endif
2901  call delete('Xscript')
2902  call delete('Xresult')
2903endfunc
2904
2905" Test vimgrep without swap file
2906func Test_vimgrep_without_swap_file()
2907  let lines =<< trim [SCRIPT]
2908    vimgrep grep test_c*
2909    call writefile(['done'], 'Xresult')
2910    qall!
2911  [SCRIPT]
2912  call writefile(lines, 'Xscript')
2913  if RunVim([], [], '--clean -n -S Xscript Xscript')
2914    call assert_equal(['done'], readfile('Xresult'))
2915  endif
2916  call delete('Xscript')
2917  call delete('Xresult')
2918endfunc
2919
2920func Test_vimgrep_existing_swapfile()
2921  call writefile(['match apple with apple'], 'Xapple')
2922  call writefile(['swapfile'], '.Xapple.swp')
2923  let g:foundSwap = 0
2924  let g:ignoreSwapExists = 1
2925  augroup grep
2926    au SwapExists * let foundSwap = 1 | let v:swapchoice = 'e'
2927  augroup END
2928  vimgrep apple Xapple
2929  call assert_equal(1, g:foundSwap)
2930  call assert_match('.Xapple.swo', swapname(''))
2931
2932  call delete('Xapple')
2933  call delete('.Xapple.swp')
2934  augroup grep
2935    au! SwapExists
2936  augroup END
2937  unlet g:ignoreSwapExists
2938endfunc
2939
2940func XfreeTests(cchar)
2941  call s:setup_commands(a:cchar)
2942
2943  enew | only
2944
2945  " Deleting the quickfix stack should work even When the current list is
2946  " somewhere in the middle of the stack
2947  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2948  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2949  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2950  Xolder
2951  call g:Xsetlist([], 'f')
2952  call assert_equal(0, len(g:Xgetlist()))
2953
2954  " After deleting the stack, adding a new list should create a stack with a
2955  " single list.
2956  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2957  call assert_equal(1, g:Xgetlist({'all':1}).nr)
2958
2959  " Deleting the stack from a quickfix window should update/clear the
2960  " quickfix/location list window.
2961  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2962  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2963  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2964  Xolder
2965  Xwindow
2966  call g:Xsetlist([], 'f')
2967  call assert_equal(2, winnr('$'))
2968  call assert_equal(1, line('$'))
2969  Xclose
2970
2971  " Deleting the stack from a non-quickfix window should update/clear the
2972  " quickfix/location list window.
2973  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2974  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2975  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2976  Xolder
2977  Xwindow
2978  wincmd p
2979  call g:Xsetlist([], 'f')
2980  call assert_equal(0, len(g:Xgetlist()))
2981  wincmd p
2982  call assert_equal(2, winnr('$'))
2983  call assert_equal(1, line('$'))
2984
2985  " After deleting the location list stack, if the location list window is
2986  " opened, then a new location list should be created. So opening the
2987  " location list window again should not create a new window.
2988  if a:cchar == 'l'
2989      lexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2990      wincmd p
2991      lopen
2992      call assert_equal(2, winnr('$'))
2993  endif
2994  Xclose
2995endfunc
2996
2997" Tests for the quickfix free functionality
2998func Test_qf_free()
2999  call XfreeTests('c')
3000  call XfreeTests('l')
3001endfunc
3002
3003" Test for buffer overflow when parsing lines and adding new entries to
3004" the quickfix list.
3005func Test_bufoverflow()
3006  set efm=%f:%l:%m
3007  cgetexpr ['File1:100:' . repeat('x', 1025)]
3008
3009  set efm=%+GCompiler:\ %.%#,%f:%l:%m
3010  cgetexpr ['Compiler: ' . repeat('a', 1015), 'File1:10:Hello World']
3011
3012  set efm=%DEntering\ directory\ %f,%f:%l:%m
3013  cgetexpr ['Entering directory ' . repeat('a', 1006),
3014	      \ 'File1:10:Hello World']
3015  set efm&vim
3016endfunc
3017
3018" Tests for getting the quickfix stack size
3019func XsizeTests(cchar)
3020  call s:setup_commands(a:cchar)
3021
3022  call g:Xsetlist([], 'f')
3023  call assert_equal(0, g:Xgetlist({'nr':'$'}).nr)
3024  call assert_equal('', g:Xgetlist({'nr':'$', 'all':1}).title)
3025  call assert_equal(0, g:Xgetlist({'nr':0}).nr)
3026
3027  Xexpr "File1:10:Line1"
3028  Xexpr "File2:20:Line2"
3029  Xexpr "File3:30:Line3"
3030  Xolder | Xolder
3031  call assert_equal(3, g:Xgetlist({'nr':'$'}).nr)
3032  call g:Xsetlist([], 'f')
3033
3034  Xexpr "File1:10:Line1"
3035  Xexpr "File2:20:Line2"
3036  Xexpr "File3:30:Line3"
3037  Xolder | Xolder
3038  call g:Xsetlist([], 'a', {'nr':'$', 'title':'Compiler'})
3039  call assert_equal('Compiler', g:Xgetlist({'nr':3, 'all':1}).title)
3040endfunc
3041
3042func Test_Qf_Size()
3043  call XsizeTests('c')
3044  call XsizeTests('l')
3045endfunc
3046
3047func Test_cclose_from_copen()
3048    augroup QF_Test
3049	au!
3050        au FileType qf :call assert_fails(':cclose', 'E788:')
3051    augroup END
3052    copen
3053    augroup QF_Test
3054	au!
3055    augroup END
3056    augroup! QF_Test
3057endfunc
3058
3059func Test_cclose_in_autocmd()
3060  " Problem is only triggered if "starting" is zero, so that the OptionsSet
3061  " event will be triggered.
3062  call test_override('starting', 1)
3063  augroup QF_Test
3064    au!
3065    au FileType qf :call assert_fails(':cclose', 'E788:')
3066  augroup END
3067  copen
3068  augroup QF_Test
3069    au!
3070  augroup END
3071  augroup! QF_Test
3072  call test_override('starting', 0)
3073endfunc
3074
3075" Check that ":file" without an argument is possible even when "curbuf_lock"
3076" is set.
3077func Test_file_from_copen()
3078  " Works without argument.
3079  augroup QF_Test
3080    au!
3081    au FileType qf file
3082  augroup END
3083  copen
3084
3085  augroup QF_Test
3086    au!
3087  augroup END
3088  cclose
3089
3090  " Fails with argument.
3091  augroup QF_Test
3092    au!
3093    au FileType qf call assert_fails(':file foo', 'E788:')
3094  augroup END
3095  copen
3096  augroup QF_Test
3097    au!
3098  augroup END
3099  cclose
3100
3101  augroup! QF_Test
3102endfunc
3103
3104func Test_resize_from_copen()
3105  augroup QF_Test
3106    au!
3107    au FileType qf resize 5
3108  augroup END
3109  try
3110    " This should succeed without any exception.  No other buffers are
3111    " involved in the autocmd.
3112    copen
3113  finally
3114    augroup QF_Test
3115      au!
3116    augroup END
3117    augroup! QF_Test
3118  endtry
3119endfunc
3120
3121func Test_vimgrep_with_textlock()
3122  new
3123
3124  " Simple way to execute something with "textwinlock" set.
3125  " Check that vimgrep without jumping can be executed.
3126  au InsertCharPre * vimgrep /RunTheTest/j runtest.vim
3127  normal ax
3128  let qflist = getqflist()
3129  call assert_true(len(qflist) > 0)
3130  call assert_match('RunTheTest', qflist[0].text)
3131  call setqflist([], 'r')
3132  au! InsertCharPre
3133
3134  " Check that vimgrepadd without jumping can be executed.
3135  au InsertCharPre * vimgrepadd /RunTheTest/j runtest.vim
3136  normal ax
3137  let qflist = getqflist()
3138  call assert_true(len(qflist) > 0)
3139  call assert_match('RunTheTest', qflist[0].text)
3140  call setqflist([], 'r')
3141  au! InsertCharPre
3142
3143  " Check that lvimgrep without jumping can be executed.
3144  au InsertCharPre * lvimgrep /RunTheTest/j runtest.vim
3145  normal ax
3146  let qflist = getloclist(0)
3147  call assert_true(len(qflist) > 0)
3148  call assert_match('RunTheTest', qflist[0].text)
3149  call setloclist(0, [], 'r')
3150  au! InsertCharPre
3151
3152  " Check that lvimgrepadd without jumping can be executed.
3153  au InsertCharPre * lvimgrepadd /RunTheTest/j runtest.vim
3154  normal ax
3155  let qflist = getloclist(0)
3156  call assert_true(len(qflist) > 0)
3157  call assert_match('RunTheTest', qflist[0].text)
3158  call setloclist(0, [], 'r')
3159  au! InsertCharPre
3160
3161  " trying to jump will give an error
3162  au InsertCharPre * vimgrep /RunTheTest/ runtest.vim
3163  call assert_fails('normal ax', 'E565:')
3164  au! InsertCharPre
3165
3166  au InsertCharPre * vimgrepadd /RunTheTest/ runtest.vim
3167  call assert_fails('normal ax', 'E565:')
3168  au! InsertCharPre
3169
3170  au InsertCharPre * lvimgrep /RunTheTest/ runtest.vim
3171  call assert_fails('normal ax', 'E565:')
3172  au! InsertCharPre
3173
3174  au InsertCharPre * lvimgrepadd /RunTheTest/ runtest.vim
3175  call assert_fails('normal ax', 'E565:')
3176  au! InsertCharPre
3177
3178  bwipe!
3179endfunc
3180
3181" Tests for the quickfix buffer b:changedtick variable
3182func Xchangedtick_tests(cchar)
3183  call s:setup_commands(a:cchar)
3184
3185  new | only
3186
3187  Xexpr "" | Xexpr "" | Xexpr ""
3188
3189  Xopen
3190  Xolder
3191  Xolder
3192  Xaddexpr "F1:10:Line10"
3193  Xaddexpr "F2:20:Line20"
3194  call g:Xsetlist([{"filename":"F3", "lnum":30, "text":"Line30"}], 'a')
3195  call g:Xsetlist([], 'f')
3196  call assert_equal(8, getbufvar('%', 'changedtick'))
3197  Xclose
3198endfunc
3199
3200func Test_changedtick()
3201  call Xchangedtick_tests('c')
3202  call Xchangedtick_tests('l')
3203endfunc
3204
3205" Tests for parsing an expression using setqflist()
3206func Xsetexpr_tests(cchar)
3207  call s:setup_commands(a:cchar)
3208
3209  let t = ["File1:10:Line10", "File1:20:Line20"]
3210  call g:Xsetlist([], ' ', {'lines' : t})
3211  call g:Xsetlist([], 'a', {'lines' : ["File1:30:Line30"]})
3212
3213  let l = g:Xgetlist()
3214  call assert_equal(3, len(l))
3215  call assert_equal(20, l[1].lnum)
3216  call assert_equal('Line30', l[2].text)
3217  call g:Xsetlist([], 'r', {'lines' : ["File2:5:Line5"]})
3218  let l = g:Xgetlist()
3219  call assert_equal(1, len(l))
3220  call assert_equal('Line5', l[0].text)
3221  call assert_equal(-1, g:Xsetlist([], 'a', {'lines' : 10}))
3222  call assert_equal(-1, g:Xsetlist([], 'a', {'lines' : "F1:10:L10"}))
3223
3224  call g:Xsetlist([], 'f')
3225  " Add entries to multiple lists
3226  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["File1:10:Line10"]})
3227  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["File2:20:Line20"]})
3228  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["File1:15:Line15"]})
3229  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["File2:25:Line25"]})
3230  call assert_equal('Line15', g:Xgetlist({'nr':1, 'items':1}).items[1].text)
3231  call assert_equal('Line25', g:Xgetlist({'nr':2, 'items':1}).items[1].text)
3232
3233  " Adding entries using a custom efm
3234  set efm&
3235  call g:Xsetlist([], ' ', {'efm' : '%f#%l#%m',
3236				\ 'lines' : ["F1#10#L10", "F2#20#L20"]})
3237  call assert_equal(20, g:Xgetlist({'items':1}).items[1].lnum)
3238  call g:Xsetlist([], 'a', {'efm' : '%f#%l#%m', 'lines' : ["F3:30:L30"]})
3239  call assert_equal('F3:30:L30', g:Xgetlist({'items':1}).items[2].text)
3240  call assert_equal(20, g:Xgetlist({'items':1}).items[1].lnum)
3241  call assert_equal(-1, g:Xsetlist([], 'a', {'efm' : [],
3242				\ 'lines' : ['F1:10:L10']}))
3243endfunc
3244
3245func Test_setexpr()
3246  call Xsetexpr_tests('c')
3247  call Xsetexpr_tests('l')
3248endfunc
3249
3250" Tests for per quickfix/location list directory stack
3251func Xmultidirstack_tests(cchar)
3252  call s:setup_commands(a:cchar)
3253
3254  call g:Xsetlist([], 'f')
3255  Xexpr "" | Xexpr ""
3256
3257  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["Entering dir 'Xone/a'"]})
3258  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["Entering dir 'Xtwo/a'"]})
3259  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["one.txt:3:one one one"]})
3260  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["two.txt:5:two two two"]})
3261
3262  let l1 = g:Xgetlist({'nr':1, 'items':1})
3263  let l2 = g:Xgetlist({'nr':2, 'items':1})
3264  call assert_equal('Xone/a/one.txt', bufname(l1.items[1].bufnr))
3265  call assert_equal(3, l1.items[1].lnum)
3266  call assert_equal('Xtwo/a/two.txt', bufname(l2.items[1].bufnr))
3267  call assert_equal(5, l2.items[1].lnum)
3268endfunc
3269
3270func Test_multidirstack()
3271  call mkdir('Xone/a', 'p')
3272  call mkdir('Xtwo/a', 'p')
3273  let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7']
3274  call writefile(lines, 'Xone/a/one.txt')
3275  call writefile(lines, 'Xtwo/a/two.txt')
3276  let save_efm = &efm
3277  set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f'
3278
3279  call Xmultidirstack_tests('c')
3280  call Xmultidirstack_tests('l')
3281
3282  let &efm = save_efm
3283  call delete('Xone', 'rf')
3284  call delete('Xtwo', 'rf')
3285endfunc
3286
3287" Tests for per quickfix/location list file stack
3288func Xmultifilestack_tests(cchar)
3289  call s:setup_commands(a:cchar)
3290
3291  call g:Xsetlist([], 'f')
3292  Xexpr "" | Xexpr ""
3293
3294  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["[one.txt]"]})
3295  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["[two.txt]"]})
3296  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["(3,5) one one one"]})
3297  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["(5,9) two two two"]})
3298
3299  let l1 = g:Xgetlist({'nr':1, 'items':1})
3300  let l2 = g:Xgetlist({'nr':2, 'items':1})
3301  call assert_equal('one.txt', bufname(l1.items[1].bufnr))
3302  call assert_equal(3, l1.items[1].lnum)
3303  call assert_equal('two.txt', bufname(l2.items[1].bufnr))
3304  call assert_equal(5, l2.items[1].lnum)
3305
3306  " Test for start of a new error line in the same line where a previous
3307  " error line ends with a file stack.
3308  let efm_val = 'Error\ l%l\ in\ %f,'
3309  let efm_val .= '%-P%>(%f%r,Error\ l%l\ in\ %m,%-Q)%r'
3310  let l = g:Xgetlist({'lines' : [
3311	      \ '(one.txt',
3312	      \ 'Error l4 in one.txt',
3313	      \ ') (two.txt',
3314	      \ 'Error l6 in two.txt',
3315	      \ ')',
3316	      \ 'Error l8 in one.txt'
3317	      \ ], 'efm' : efm_val})
3318  call assert_equal(3, len(l.items))
3319  call assert_equal('one.txt', bufname(l.items[0].bufnr))
3320  call assert_equal(4, l.items[0].lnum)
3321  call assert_equal('one.txt', l.items[0].text)
3322  call assert_equal('two.txt', bufname(l.items[1].bufnr))
3323  call assert_equal(6, l.items[1].lnum)
3324  call assert_equal('two.txt', l.items[1].text)
3325  call assert_equal('one.txt', bufname(l.items[2].bufnr))
3326  call assert_equal(8, l.items[2].lnum)
3327  call assert_equal('', l.items[2].text)
3328endfunc
3329
3330func Test_multifilestack()
3331  let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7']
3332  call writefile(lines, 'one.txt')
3333  call writefile(lines, 'two.txt')
3334  let save_efm = &efm
3335  set efm=%+P[%f],(%l\\,%c)\ %m,%-Q
3336
3337  call Xmultifilestack_tests('c')
3338  call Xmultifilestack_tests('l')
3339
3340  let &efm = save_efm
3341  call delete('one.txt')
3342  call delete('two.txt')
3343endfunc
3344
3345" Tests for per buffer 'efm' setting
3346func Test_perbuf_efm()
3347  call writefile(["File1-10-Line10"], 'one.txt')
3348  call writefile(["File2#20#Line20"], 'two.txt')
3349  set efm=%f#%l#%m
3350  new | only
3351  new
3352  setlocal efm=%f-%l-%m
3353  cfile one.txt
3354  wincmd w
3355  caddfile two.txt
3356
3357  let l = getqflist()
3358  call assert_equal(10, l[0].lnum)
3359  call assert_equal('Line20', l[1].text)
3360
3361  set efm&
3362  new | only
3363  call delete('one.txt')
3364  call delete('two.txt')
3365endfunc
3366
3367" Open multiple help windows using ":lhelpgrep
3368" This test used to crash Vim
3369func Test_Multi_LL_Help()
3370  new | only
3371  lhelpgrep window
3372  lopen
3373  e#
3374  lhelpgrep buffer
3375  call assert_equal(3, winnr('$'))
3376  call assert_true(len(getloclist(1)) != 0)
3377  call assert_true(len(getloclist(2)) != 0)
3378  new | only
3379endfunc
3380
3381" Tests for adding new quickfix lists using setqflist()
3382func XaddQf_tests(cchar)
3383  call s:setup_commands(a:cchar)
3384
3385  " Create a new list using ' ' for action
3386  call g:Xsetlist([], 'f')
3387  call g:Xsetlist([], ' ', {'title' : 'Test1'})
3388  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3389  call assert_equal(1, l.nr)
3390  call assert_equal('Test1', l.title)
3391
3392  " Create a new list using ' ' for action and '$' for 'nr'
3393  call g:Xsetlist([], 'f')
3394  call g:Xsetlist([], ' ', {'title' : 'Test2', 'nr' : '$'})
3395  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3396  call assert_equal(1, l.nr)
3397  call assert_equal('Test2', l.title)
3398
3399  " Create a new list using 'a' for action
3400  call g:Xsetlist([], 'f')
3401  call g:Xsetlist([], 'a', {'title' : 'Test3'})
3402  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3403  call assert_equal(1, l.nr)
3404  call assert_equal('Test3', l.title)
3405
3406  " Create a new list using 'a' for action and '$' for 'nr'
3407  call g:Xsetlist([], 'f')
3408  call g:Xsetlist([], 'a', {'title' : 'Test3', 'nr' : '$'})
3409  call g:Xsetlist([], 'a', {'title' : 'Test4'})
3410  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3411  call assert_equal(1, l.nr)
3412  call assert_equal('Test4', l.title)
3413
3414  " Adding a quickfix list should remove all the lists following the current
3415  " list.
3416  Xexpr "" | Xexpr "" | Xexpr ""
3417  silent! 10Xolder
3418  call g:Xsetlist([], ' ', {'title' : 'Test5'})
3419  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3420  call assert_equal(2, l.nr)
3421  call assert_equal('Test5', l.title)
3422
3423  " Add a quickfix list using '$' as the list number.
3424  let lastqf = g:Xgetlist({'nr':'$'}).nr
3425  silent! 99Xolder
3426  call g:Xsetlist([], ' ', {'nr' : '$', 'title' : 'Test6'})
3427  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3428  call assert_equal(lastqf + 1, l.nr)
3429  call assert_equal('Test6', l.title)
3430
3431  " Add a quickfix list using 'nr' set to one more than the quickfix
3432  " list size.
3433  let lastqf = g:Xgetlist({'nr':'$'}).nr
3434  silent! 99Xolder
3435  call g:Xsetlist([], ' ', {'nr' : lastqf + 1, 'title' : 'Test7'})
3436  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3437  call assert_equal(lastqf + 1, l.nr)
3438  call assert_equal('Test7', l.title)
3439
3440  " Add a quickfix list to a stack with 10 lists using 'nr' set to '$'
3441  exe repeat('Xexpr "" |', 9) . 'Xexpr ""'
3442  silent! 99Xolder
3443  call g:Xsetlist([], ' ', {'nr' : '$', 'title' : 'Test8'})
3444  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3445  call assert_equal(10, l.nr)
3446  call assert_equal('Test8', l.title)
3447
3448  " Add a quickfix list using 'nr' set to a value greater than 10
3449  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : 12, 'title' : 'Test9'}))
3450
3451  " Try adding a quickfix list with 'nr' set to a value greater than the
3452  " quickfix list size but less than 10.
3453  call g:Xsetlist([], 'f')
3454  Xexpr "" | Xexpr "" | Xexpr ""
3455  silent! 99Xolder
3456  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : 8, 'title' : 'Test10'}))
3457
3458  " Add a quickfix list using 'nr' set to a some string or list
3459  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : [1,2], 'title' : 'Test11'}))
3460endfunc
3461
3462func Test_add_qf()
3463  call XaddQf_tests('c')
3464  call XaddQf_tests('l')
3465endfunc
3466
3467" Test for getting the quickfix list items from some text without modifying
3468" the quickfix stack
3469func XgetListFromLines(cchar)
3470  call s:setup_commands(a:cchar)
3471  call g:Xsetlist([], 'f')
3472
3473  let l = g:Xgetlist({'lines' : ["File2:20:Line20", "File2:30:Line30"]}).items
3474  call assert_equal(2, len(l))
3475  call assert_equal(30, l[1].lnum)
3476
3477  call assert_equal({}, g:Xgetlist({'lines' : 10}))
3478  call assert_equal({}, g:Xgetlist({'lines' : 'File1:10:Line10'}))
3479  call assert_equal([], g:Xgetlist({'lines' : []}).items)
3480  call assert_equal([], g:Xgetlist({'lines' : [10, 20]}).items)
3481
3482  " Parse text using a custom efm
3483  set efm&
3484  let l = g:Xgetlist({'lines':['File3#30#Line30'], 'efm' : '%f#%l#%m'}).items
3485  call assert_equal('Line30', l[0].text)
3486  let l = g:Xgetlist({'lines':['File3:30:Line30'], 'efm' : '%f-%l-%m'}).items
3487  call assert_equal('File3:30:Line30', l[0].text)
3488  let l = g:Xgetlist({'lines':['File3:30:Line30'], 'efm' : [1,2]})
3489  call assert_equal({}, l)
3490  call assert_fails("call g:Xgetlist({'lines':['abc'], 'efm':'%2'})", 'E376:')
3491  call assert_fails("call g:Xgetlist({'lines':['abc'], 'efm':''})", 'E378:')
3492
3493  " Make sure that the quickfix stack is not modified
3494  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
3495endfunc
3496
3497func Test_get_list_from_lines()
3498  call XgetListFromLines('c')
3499  call XgetListFromLines('l')
3500endfunc
3501
3502" Tests for the quickfix list id
3503func Xqfid_tests(cchar)
3504  call s:setup_commands(a:cchar)
3505
3506  call g:Xsetlist([], 'f')
3507  call assert_equal(0, g:Xgetlist({'id':0}).id)
3508  Xexpr ''
3509  let start_id = g:Xgetlist({'id' : 0}).id
3510  Xexpr '' | Xexpr ''
3511  Xolder
3512  call assert_equal(start_id, g:Xgetlist({'id':0, 'nr':1}).id)
3513  call assert_equal(start_id + 1, g:Xgetlist({'id':0, 'nr':0}).id)
3514  call assert_equal(start_id + 2, g:Xgetlist({'id':0, 'nr':'$'}).id)
3515  call assert_equal(0, g:Xgetlist({'id':0, 'nr':99}).id)
3516  call assert_equal(2, g:Xgetlist({'id':start_id + 1, 'nr':0}).nr)
3517  call assert_equal(0, g:Xgetlist({'id':99, 'nr':0}).id)
3518  call assert_equal(0, g:Xgetlist({'id':"abc", 'nr':0}).id)
3519
3520  call g:Xsetlist([], 'a', {'id':start_id, 'context':[1,2]})
3521  call assert_equal([1,2], g:Xgetlist({'nr':1, 'context':1}).context)
3522  call g:Xsetlist([], 'a', {'id':start_id+1, 'lines':['F1:10:L10']})
3523  call assert_equal('L10', g:Xgetlist({'nr':2, 'items':1}).items[0].text)
3524  call assert_equal(-1, g:Xsetlist([], 'a', {'id':999, 'title':'Vim'}))
3525  call assert_equal(-1, g:Xsetlist([], 'a', {'id':'abc', 'title':'Vim'}))
3526
3527  let qfid = g:Xgetlist({'id':0, 'nr':0})
3528  call g:Xsetlist([], 'f')
3529  call assert_equal(0, g:Xgetlist({'id':qfid, 'nr':0}).id)
3530endfunc
3531
3532func Test_qf_id()
3533  call Xqfid_tests('c')
3534  call Xqfid_tests('l')
3535endfunc
3536
3537func Xqfjump_tests(cchar)
3538  call s:setup_commands(a:cchar)
3539
3540  call writefile(["Line1\tFoo", "Line2"], 'F1')
3541  call writefile(["Line1\tBar", "Line2"], 'F2')
3542  call writefile(["Line1\tBaz", "Line2"], 'F3')
3543
3544  call g:Xsetlist([], 'f')
3545
3546  " Tests for
3547  "   Jumping to a line using a pattern
3548  "   Jumping to a column greater than the last column in a line
3549  "   Jumping to a line greater than the last line in the file
3550  let l = []
3551  for i in range(1, 7)
3552    call add(l, {})
3553  endfor
3554  let l[0].filename='F1'
3555  let l[0].pattern='Line1'
3556  let l[1].filename='F2'
3557  let l[1].pattern='Line1'
3558  let l[2].filename='F3'
3559  let l[2].pattern='Line1'
3560  let l[3].filename='F3'
3561  let l[3].lnum=1
3562  let l[3].col=9
3563  let l[3].vcol=1
3564  let l[4].filename='F3'
3565  let l[4].lnum=99
3566  let l[5].filename='F3'
3567  let l[5].lnum=1
3568  let l[5].col=99
3569  let l[5].vcol=1
3570  let l[6].filename='F3'
3571  let l[6].pattern='abcxyz'
3572
3573  call g:Xsetlist([], ' ', {'items' : l})
3574  Xopen | only
3575  2Xnext
3576  call assert_equal(3, g:Xgetlist({'idx' : 0}).idx)
3577  call assert_equal('F3', @%)
3578  Xnext
3579  call assert_equal(7, col('.'))
3580  Xnext
3581  call assert_equal(2, line('.'))
3582  Xnext
3583  call assert_equal(9, col('.'))
3584  2
3585  Xnext
3586  call assert_equal(2, line('.'))
3587
3588  if a:cchar == 'l'
3589    " When jumping to a location list entry in the location list window and
3590    " no usable windows are available, then a new window should be opened.
3591    enew! | new | only
3592    call g:Xsetlist([], 'f')
3593    setlocal buftype=nofile
3594    new
3595    call g:Xsetlist([], ' ', {'lines' : ['F1:1:1:Line1', 'F1:2:2:Line2', 'F2:1:1:Line1', 'F2:2:2:Line2', 'F3:1:1:Line1', 'F3:2:2:Line2']})
3596    Xopen
3597    let winid = win_getid()
3598    wincmd p
3599    close
3600    call win_gotoid(winid)
3601    Xnext
3602    call assert_equal(3, winnr('$'))
3603    call assert_equal(1, winnr())
3604    call assert_equal(2, line('.'))
3605
3606    " When jumping to an entry in the location list window and the window
3607    " associated with the location list is not present and a window containing
3608    " the file is already present, then that window should be used.
3609    close
3610    belowright new
3611    call g:Xsetlist([], 'f')
3612    edit F3
3613    call win_gotoid(winid)
3614    Xlast
3615    call assert_equal(3, winnr())
3616    call assert_equal(6, g:Xgetlist({'size' : 1}).size)
3617    call assert_equal(winid, g:Xgetlist({'winid' : 1}).winid)
3618  endif
3619
3620  " Cleanup
3621  enew!
3622  new | only
3623
3624  call delete('F1')
3625  call delete('F2')
3626  call delete('F3')
3627endfunc
3628
3629func Test_qfjump()
3630  call Xqfjump_tests('c')
3631  call Xqfjump_tests('l')
3632endfunc
3633
3634" Tests for the getqflist() and getloclist() functions when the list is not
3635" present or is empty
3636func Xgetlist_empty_tests(cchar)
3637  call s:setup_commands(a:cchar)
3638
3639  " Empty quickfix stack
3640  call g:Xsetlist([], 'f')
3641  call assert_equal('', g:Xgetlist({'context' : 0}).context)
3642  call assert_equal(0, g:Xgetlist({'id' : 0}).id)
3643  call assert_equal(0, g:Xgetlist({'idx' : 0}).idx)
3644  call assert_equal([], g:Xgetlist({'items' : 0}).items)
3645  call assert_equal(0, g:Xgetlist({'nr' : 0}).nr)
3646  call assert_equal(0, g:Xgetlist({'size' : 0}).size)
3647  call assert_equal('', g:Xgetlist({'title' : 0}).title)
3648  call assert_equal(0, g:Xgetlist({'winid' : 0}).winid)
3649  call assert_equal(0, g:Xgetlist({'changedtick' : 0}).changedtick)
3650  if a:cchar == 'c'
3651    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0,
3652		  \ 'items' : [], 'nr' : 0, 'size' : 0, 'qfbufnr' : 0,
3653		  \ 'title' : '', 'winid' : 0, 'changedtick': 0,
3654                  \ 'quickfixtextfunc' : ''}, g:Xgetlist({'all' : 0}))
3655  else
3656    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0,
3657		\ 'items' : [], 'nr' : 0, 'size' : 0, 'title' : '',
3658		\ 'winid' : 0, 'changedtick': 0, 'filewinid' : 0,
3659		\ 'qfbufnr' : 0, 'quickfixtextfunc' : ''},
3660		\ g:Xgetlist({'all' : 0}))
3661  endif
3662
3663  " Quickfix window with empty stack
3664  silent! Xopen
3665  let qfwinid = (a:cchar == 'c') ? win_getid() : 0
3666  let qfbufnr = (a:cchar == 'c') ? bufnr('') : 0
3667  call assert_equal(qfwinid, g:Xgetlist({'winid' : 0}).winid)
3668  Xclose
3669
3670  " Empty quickfix list
3671  Xexpr ""
3672  call assert_equal('', g:Xgetlist({'context' : 0}).context)
3673  call assert_notequal(0, g:Xgetlist({'id' : 0}).id)
3674  call assert_equal(0, g:Xgetlist({'idx' : 0}).idx)
3675  call assert_equal([], g:Xgetlist({'items' : 0}).items)
3676  call assert_notequal(0, g:Xgetlist({'nr' : 0}).nr)
3677  call assert_equal(0, g:Xgetlist({'size' : 0}).size)
3678  call assert_notequal('', g:Xgetlist({'title' : 0}).title)
3679  call assert_equal(0, g:Xgetlist({'winid' : 0}).winid)
3680  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3681
3682  let qfid = g:Xgetlist({'id' : 0}).id
3683  call g:Xsetlist([], 'f')
3684
3685  " Non-existing quickfix identifier
3686  call assert_equal('', g:Xgetlist({'id' : qfid, 'context' : 0}).context)
3687  call assert_equal(0, g:Xgetlist({'id' : qfid}).id)
3688  call assert_equal(0, g:Xgetlist({'id' : qfid, 'idx' : 0}).idx)
3689  call assert_equal([], g:Xgetlist({'id' : qfid, 'items' : 0}).items)
3690  call assert_equal(0, g:Xgetlist({'id' : qfid, 'nr' : 0}).nr)
3691  call assert_equal(0, g:Xgetlist({'id' : qfid, 'size' : 0}).size)
3692  call assert_equal('', g:Xgetlist({'id' : qfid, 'title' : 0}).title)
3693  call assert_equal(0, g:Xgetlist({'id' : qfid, 'winid' : 0}).winid)
3694  call assert_equal(0, g:Xgetlist({'id' : qfid, 'changedtick' : 0}).changedtick)
3695  if a:cchar == 'c'
3696    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
3697		\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
3698		\ 'qfbufnr' : qfbufnr, 'quickfixtextfunc' : '',
3699		\ 'changedtick' : 0}, g:Xgetlist({'id' : qfid, 'all' : 0}))
3700  else
3701    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
3702		\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
3703		\ 'changedtick' : 0, 'filewinid' : 0, 'qfbufnr' : 0,
3704                \ 'quickfixtextfunc' : ''},
3705		\ g:Xgetlist({'id' : qfid, 'all' : 0}))
3706  endif
3707
3708  " Non-existing quickfix list number
3709  call assert_equal('', g:Xgetlist({'nr' : 5, 'context' : 0}).context)
3710  call assert_equal(0, g:Xgetlist({'nr' : 5}).nr)
3711  call assert_equal(0, g:Xgetlist({'nr' : 5, 'idx' : 0}).idx)
3712  call assert_equal([], g:Xgetlist({'nr' : 5, 'items' : 0}).items)
3713  call assert_equal(0, g:Xgetlist({'nr' : 5, 'id' : 0}).id)
3714  call assert_equal(0, g:Xgetlist({'nr' : 5, 'size' : 0}).size)
3715  call assert_equal('', g:Xgetlist({'nr' : 5, 'title' : 0}).title)
3716  call assert_equal(0, g:Xgetlist({'nr' : 5, 'winid' : 0}).winid)
3717  call assert_equal(0, g:Xgetlist({'nr' : 5, 'changedtick' : 0}).changedtick)
3718  if a:cchar == 'c'
3719    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
3720		\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
3721		\ 'changedtick' : 0, 'qfbufnr' : qfbufnr,
3722                \ 'quickfixtextfunc' : ''}, g:Xgetlist({'nr' : 5, 'all' : 0}))
3723  else
3724    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
3725		\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
3726		\ 'changedtick' : 0, 'filewinid' : 0, 'qfbufnr' : 0,
3727                \ 'quickfixtextfunc' : ''}, g:Xgetlist({'nr' : 5, 'all' : 0}))
3728  endif
3729endfunc
3730
3731func Test_getqflist()
3732  call Xgetlist_empty_tests('c')
3733  call Xgetlist_empty_tests('l')
3734endfunc
3735
3736func Test_getqflist_invalid_nr()
3737  " The following commands used to crash Vim
3738  cexpr ""
3739  call getqflist({'nr' : $XXX_DOES_NOT_EXIST_XXX})
3740
3741  " Cleanup
3742  call setqflist([], 'r')
3743endfunc
3744
3745" Tests for the quickfix/location list changedtick
3746func Xqftick_tests(cchar)
3747  call s:setup_commands(a:cchar)
3748
3749  call g:Xsetlist([], 'f')
3750
3751  Xexpr "F1:10:Line10"
3752  let qfid = g:Xgetlist({'id' : 0}).id
3753  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3754  Xaddexpr "F2:20:Line20\nF2:21:Line21"
3755  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
3756  call g:Xsetlist([], 'a', {'lines' : ["F3:30:Line30", "F3:31:Line31"]})
3757  call assert_equal(3, g:Xgetlist({'changedtick' : 0}).changedtick)
3758  call g:Xsetlist([], 'r', {'lines' : ["F4:40:Line40"]})
3759  call assert_equal(4, g:Xgetlist({'changedtick' : 0}).changedtick)
3760  call g:Xsetlist([], 'a', {'title' : 'New Title'})
3761  call assert_equal(5, g:Xgetlist({'changedtick' : 0}).changedtick)
3762
3763  enew!
3764  call append(0, ["F5:50:L50", "F6:60:L60"])
3765  Xaddbuffer
3766  call assert_equal(6, g:Xgetlist({'changedtick' : 0}).changedtick)
3767  enew!
3768
3769  call g:Xsetlist([], 'a', {'context' : {'bus' : 'pci'}})
3770  call assert_equal(7, g:Xgetlist({'changedtick' : 0}).changedtick)
3771  call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'},
3772	      \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], 'a')
3773  call assert_equal(8, g:Xgetlist({'changedtick' : 0}).changedtick)
3774  call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'},
3775	      \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], ' ')
3776  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3777  call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'},
3778	      \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], 'r')
3779  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
3780
3781  call writefile(["F8:80:L80", "F8:81:L81"], "Xone")
3782  Xfile Xone
3783  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3784  Xaddfile Xone
3785  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
3786
3787  " Test case for updating a non-current quickfix list
3788  call g:Xsetlist([], 'f')
3789  Xexpr "F1:1:L1"
3790  Xexpr "F2:2:L2"
3791  call g:Xsetlist([], 'a', {'nr' : 1, "lines" : ["F10:10:L10"]})
3792  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3793  call assert_equal(2, g:Xgetlist({'nr' : 1, 'changedtick' : 0}).changedtick)
3794
3795  call delete("Xone")
3796endfunc
3797
3798func Test_qf_tick()
3799  call Xqftick_tests('c')
3800  call Xqftick_tests('l')
3801endfunc
3802
3803" Test helpgrep with lang specifier
3804func Xtest_helpgrep_with_lang_specifier(cchar)
3805  call s:setup_commands(a:cchar)
3806  Xhelpgrep Vim@en
3807  call assert_equal('help', &filetype)
3808  call assert_notequal(0, g:Xgetlist({'nr' : '$'}).nr)
3809  new | only
3810endfunc
3811
3812func Test_helpgrep_with_lang_specifier()
3813  call Xtest_helpgrep_with_lang_specifier('c')
3814  call Xtest_helpgrep_with_lang_specifier('l')
3815endfunc
3816
3817" The following test used to crash Vim.
3818" Open the location list window and close the regular window associated with
3819" the location list. When the garbage collection runs now, it incorrectly
3820" marks the location list context as not in use and frees the context.
3821func Test_ll_window_ctx()
3822  call setloclist(0, [], 'f')
3823  call setloclist(0, [], 'a', {'context' : []})
3824  lopen | only
3825  call test_garbagecollect_now()
3826  echo getloclist(0, {'context' : 1}).context
3827  enew | only
3828endfunc
3829
3830" The following test used to crash vim
3831func Test_lfile_crash()
3832  sp Xtest
3833  au QuickFixCmdPre * bw
3834  call assert_fails('lfile', 'E40:')
3835  au! QuickFixCmdPre
3836endfunc
3837
3838" The following test used to crash vim
3839func Test_lbuffer_crash()
3840  sv Xtest
3841  augroup QF_Test
3842    au!
3843    au QuickFixCmdPre,QuickFixCmdPost,BufEnter,BufLeave * bw
3844  augroup END
3845  lbuffer
3846  augroup QF_Test
3847    au!
3848  augroup END
3849endfunc
3850
3851" The following test used to crash vim
3852func Test_lexpr_crash()
3853  augroup QF_Test
3854    au!
3855    au QuickFixCmdPre,QuickFixCmdPost,BufEnter,BufLeave * call setloclist(0, [], 'f')
3856  augroup END
3857  lexpr ""
3858  augroup QF_Test
3859    au!
3860  augroup END
3861
3862  enew | only
3863  augroup QF_Test
3864    au!
3865    au BufNew * call setloclist(0, [], 'f')
3866  augroup END
3867  lexpr 'x:1:x'
3868  augroup QF_Test
3869    au!
3870  augroup END
3871
3872  enew | only
3873  lexpr ''
3874  lopen
3875  augroup QF_Test
3876    au!
3877    au FileType * call setloclist(0, [], 'f')
3878  augroup END
3879  lexpr ''
3880  augroup QF_Test
3881    au!
3882  augroup END
3883endfunc
3884
3885" The following test used to crash Vim
3886func Test_lvimgrep_crash()
3887  sv Xtest
3888  augroup QF_Test
3889    au!
3890    au QuickFixCmdPre,QuickFixCmdPost,BufEnter,BufLeave * call setloclist(0, [], 'f')
3891  augroup END
3892  lvimgrep quickfix test_quickfix.vim
3893  augroup QF_Test
3894    au!
3895  augroup END
3896
3897  new | only
3898  augroup QF_Test
3899    au!
3900    au BufEnter * call setloclist(0, [], 'r')
3901  augroup END
3902  call assert_fails('lvimgrep Test_lvimgrep_crash *', 'E926:')
3903  augroup QF_Test
3904    au!
3905  augroup END
3906
3907  enew | only
3908endfunc
3909
3910func Test_lvimgrep_crash2()
3911  au BufNewFile x sfind
3912  call assert_fails('lvimgrep x x', 'E471:')
3913  call assert_fails('lvimgrep x x x', 'E471:')
3914
3915  au! BufNewFile
3916endfunc
3917
3918" Test for the position of the quickfix and location list window
3919func Test_qfwin_pos()
3920  " Open two windows
3921  new | only
3922  new
3923  cexpr ['F1:10:L10']
3924  copen
3925  " Quickfix window should be the bottom most window
3926  call assert_equal(3, winnr())
3927  close
3928  " Open at the very top
3929  wincmd t
3930  topleft copen
3931  call assert_equal(1, winnr())
3932  close
3933  " open left of the current window
3934  wincmd t
3935  below new
3936  leftabove copen
3937  call assert_equal(2, winnr())
3938  close
3939  " open right of the current window
3940  rightbelow copen
3941  call assert_equal(3, winnr())
3942  close
3943endfunc
3944
3945" Tests for quickfix/location lists changed by autocommands when
3946" :vimgrep/:lvimgrep commands are running.
3947func Test_vimgrep_autocmd()
3948  call setqflist([], 'f')
3949  call writefile(['stars'], 'Xtest1.txt')
3950  call writefile(['stars'], 'Xtest2.txt')
3951
3952  " Test 1:
3953  " When searching for a pattern using :vimgrep, if the quickfix list is
3954  " changed by an autocmd, the results should be added to the correct quickfix
3955  " list.
3956  autocmd BufRead Xtest2.txt cexpr '' | cexpr ''
3957  silent vimgrep stars Xtest*.txt
3958  call assert_equal(1, getqflist({'nr' : 0}).nr)
3959  call assert_equal(3, getqflist({'nr' : '$'}).nr)
3960  call assert_equal('Xtest2.txt', bufname(getqflist()[1].bufnr))
3961  au! BufRead Xtest2.txt
3962
3963  " Test 2:
3964  " When searching for a pattern using :vimgrep, if the quickfix list is
3965  " freed, then a error should be given.
3966  silent! %bwipe!
3967  call setqflist([], 'f')
3968  autocmd BufRead Xtest2.txt for i in range(10) | cexpr '' | endfor
3969  call assert_fails('vimgrep stars Xtest*.txt', 'E925:')
3970  au! BufRead Xtest2.txt
3971
3972  " Test 3:
3973  " When searching for a pattern using :lvimgrep, if the location list is
3974  " freed, then the command should error out.
3975  silent! %bwipe!
3976  let g:save_winid = win_getid()
3977  autocmd BufRead Xtest2.txt call setloclist(g:save_winid, [], 'f')
3978  call assert_fails('lvimgrep stars Xtest*.txt', 'E926:')
3979  au! BufRead Xtest2.txt
3980
3981  call delete('Xtest1.txt')
3982  call delete('Xtest2.txt')
3983  call setqflist([], 'f')
3984endfunc
3985
3986" Test for an autocmd changing the current directory when running vimgrep
3987func Xvimgrep_autocmd_cd(cchar)
3988  call s:setup_commands(a:cchar)
3989
3990  %bwipe
3991  let save_cwd = getcwd()
3992
3993  augroup QF_Test
3994    au!
3995    autocmd BufRead * silent cd %:p:h
3996  augroup END
3997
3998  10Xvimgrep /vim/ Xdir/**
3999  let l = g:Xgetlist()
4000  call assert_equal('f1.txt', bufname(l[0].bufnr))
4001  call assert_equal('f2.txt', fnamemodify(bufname(l[2].bufnr), ':t'))
4002
4003  augroup QF_Test
4004    au!
4005  augroup END
4006
4007  exe 'cd ' . save_cwd
4008endfunc
4009
4010func Test_vimgrep_autocmd_cd()
4011  call mkdir('Xdir/a', 'p')
4012  call mkdir('Xdir/b', 'p')
4013  call writefile(['a_L1_vim', 'a_L2_vim'], 'Xdir/a/f1.txt')
4014  call writefile(['b_L1_vim', 'b_L2_vim'], 'Xdir/b/f2.txt')
4015  call Xvimgrep_autocmd_cd('c')
4016  call Xvimgrep_autocmd_cd('l')
4017  %bwipe
4018  call delete('Xdir', 'rf')
4019endfunc
4020
4021" The following test used to crash Vim
4022func Test_lhelpgrep_autocmd()
4023  lhelpgrep quickfix
4024  autocmd QuickFixCmdPost * call setloclist(0, [], 'f')
4025  lhelpgrep buffer
4026  call assert_equal('help', &filetype)
4027  call assert_equal(0, getloclist(0, {'nr' : '$'}).nr)
4028  lhelpgrep tabpage
4029  call assert_equal('help', &filetype)
4030  call assert_equal(1, getloclist(0, {'nr' : '$'}).nr)
4031  au! QuickFixCmdPost
4032
4033  new | only
4034  augroup QF_Test
4035    au!
4036    au BufEnter * call setqflist([], 'f')
4037  augroup END
4038  call assert_fails('helpgrep quickfix', 'E925:')
4039  " run the test with a help window already open
4040  help
4041  wincmd w
4042  call assert_fails('helpgrep quickfix', 'E925:')
4043  augroup QF_Test
4044    au! BufEnter
4045  augroup END
4046
4047  new | only
4048  augroup QF_Test
4049    au!
4050    au BufEnter * call setqflist([], 'r')
4051  augroup END
4052  call assert_fails('helpgrep quickfix', 'E925:')
4053  augroup QF_Test
4054    au! BufEnter
4055  augroup END
4056
4057  new | only
4058  augroup QF_Test
4059    au!
4060    au BufEnter * call setloclist(0, [], 'r')
4061  augroup END
4062  call assert_fails('lhelpgrep quickfix', 'E926:')
4063  augroup QF_Test
4064    au! BufEnter
4065  augroup END
4066
4067  new | only
4068endfunc
4069
4070" Test for shortening/simplifying the file name when opening the
4071" quickfix window or when displaying the quickfix list
4072func Test_shorten_fname()
4073  CheckUnix
4074  %bwipe
4075  " Create a quickfix list with a absolute path filename
4076  let fname = getcwd() . '/test_quickfix.vim'
4077  call setqflist([], ' ', {'lines':[fname . ":20:Line20"], 'efm':'%f:%l:%m'})
4078  call assert_equal(fname, bufname('test_quickfix.vim'))
4079  " Opening the quickfix window should simplify the file path
4080  cwindow
4081  call assert_equal('test_quickfix.vim', bufname('test_quickfix.vim'))
4082  cclose
4083  %bwipe
4084  " Create a quickfix list with a absolute path filename
4085  call setqflist([], ' ', {'lines':[fname . ":20:Line20"], 'efm':'%f:%l:%m'})
4086  call assert_equal(fname, bufname('test_quickfix.vim'))
4087  " Displaying the quickfix list should simplify the file path
4088  silent! clist
4089  call assert_equal('test_quickfix.vim', bufname('test_quickfix.vim'))
4090  " Add a few entries for the same file with different paths and check whether
4091  " the buffer name is shortened
4092  %bwipe
4093  call setqflist([], 'f')
4094  call setqflist([{'filename' : 'test_quickfix.vim', 'lnum' : 10},
4095        \ {'filename' : '../testdir/test_quickfix.vim', 'lnum' : 20},
4096        \ {'filename' : fname, 'lnum' : 30}], ' ')
4097  copen
4098  call assert_equal(['test_quickfix.vim|10| ',
4099        \ 'test_quickfix.vim|20| ',
4100        \ 'test_quickfix.vim|30| '], getline(1, '$'))
4101  cclose
4102endfunc
4103
4104" Quickfix title tests
4105" In the below tests, 'exe "cmd"' is used to invoke the quickfix commands.
4106" Otherwise due to indentation, the title is set with spaces at the beginning
4107" of the command.
4108func Test_qftitle()
4109  call writefile(["F1:1:Line1"], 'Xerr')
4110
4111  " :cexpr
4112  exe "cexpr readfile('Xerr')"
4113  call assert_equal(":cexpr readfile('Xerr')", getqflist({'title' : 1}).title)
4114
4115  " :cgetexpr
4116  exe "cgetexpr readfile('Xerr')"
4117  call assert_equal(":cgetexpr readfile('Xerr')",
4118					\ getqflist({'title' : 1}).title)
4119
4120  " :caddexpr
4121  call setqflist([], 'f')
4122  exe "caddexpr readfile('Xerr')"
4123  call assert_equal(":caddexpr readfile('Xerr')",
4124					\ getqflist({'title' : 1}).title)
4125
4126  " :cbuffer
4127  new Xerr
4128  exe "cbuffer"
4129  call assert_equal(':cbuffer (Xerr)', getqflist({'title' : 1}).title)
4130
4131  " :cgetbuffer
4132  edit Xerr
4133  exe "cgetbuffer"
4134  call assert_equal(':cgetbuffer (Xerr)', getqflist({'title' : 1}).title)
4135
4136  " :caddbuffer
4137  call setqflist([], 'f')
4138  edit Xerr
4139  exe "caddbuffer"
4140  call assert_equal(':caddbuffer (Xerr)', getqflist({'title' : 1}).title)
4141
4142  " :cfile
4143  exe "cfile Xerr"
4144  call assert_equal(':cfile Xerr', getqflist({'title' : 1}).title)
4145
4146  " :cgetfile
4147  exe "cgetfile Xerr"
4148  call assert_equal(':cgetfile Xerr', getqflist({'title' : 1}).title)
4149
4150  " :caddfile
4151  call setqflist([], 'f')
4152  exe "caddfile Xerr"
4153  call assert_equal(':caddfile Xerr', getqflist({'title' : 1}).title)
4154
4155  " :grep
4156  set grepprg=internal
4157  exe "grep F1 Xerr"
4158  call assert_equal(':grep F1 Xerr', getqflist({'title' : 1}).title)
4159
4160  " :grepadd
4161  call setqflist([], 'f')
4162  exe "grepadd F1 Xerr"
4163  call assert_equal(':grepadd F1 Xerr', getqflist({'title' : 1}).title)
4164  set grepprg&vim
4165
4166  " :vimgrep
4167  exe "vimgrep F1 Xerr"
4168  call assert_equal(':vimgrep F1 Xerr', getqflist({'title' : 1}).title)
4169
4170  " :vimgrepadd
4171  call setqflist([], 'f')
4172  exe "vimgrepadd F1 Xerr"
4173  call assert_equal(':vimgrepadd F1 Xerr', getqflist({'title' : 1}).title)
4174
4175  call setqflist(['F1:10:L10'], ' ')
4176  call assert_equal(':setqflist()', getqflist({'title' : 1}).title)
4177
4178  call setqflist([], 'f')
4179  call setqflist(['F1:10:L10'], 'a')
4180  call assert_equal(':setqflist()', getqflist({'title' : 1}).title)
4181
4182  call setqflist([], 'f')
4183  call setqflist(['F1:10:L10'], 'r')
4184  call assert_equal(':setqflist()', getqflist({'title' : 1}).title)
4185
4186  close
4187  call delete('Xerr')
4188
4189  call setqflist([], ' ', {'title' : 'Errors'})
4190  copen
4191  call assert_equal('Errors', w:quickfix_title)
4192  call setqflist([], 'r', {'items' : [{'filename' : 'a.c', 'lnum' : 10}]})
4193  call assert_equal('Errors', w:quickfix_title)
4194  cclose
4195
4196  " Switching to another quickfix list in one tab page should update the
4197  " quickfix window title and statusline in all the other tab pages also
4198  call setqflist([], 'f')
4199  %bw!
4200  cgetexpr ['file_one:1:1: error in the first quickfix list']
4201  call setqflist([], 'a', {'title': 'first quickfix list'})
4202  cgetexpr ['file_two:2:1: error in the second quickfix list']
4203  call setqflist([], 'a', {'title': 'second quickfix list'})
4204  copen
4205  wincmd t
4206  tabnew two
4207  copen
4208  wincmd t
4209  colder
4210  call assert_equal('first quickfix list', gettabwinvar(1, 2, 'quickfix_title'))
4211  call assert_equal('first quickfix list', gettabwinvar(2, 2, 'quickfix_title'))
4212  call assert_equal(1, tabpagewinnr(1))
4213  call assert_equal(1, tabpagewinnr(2))
4214  tabnew
4215  call setqflist([], 'a', {'title': 'new quickfix title'})
4216  call assert_equal('new quickfix title', gettabwinvar(1, 2, 'quickfix_title'))
4217  call assert_equal('new quickfix title', gettabwinvar(2, 2, 'quickfix_title'))
4218  %bw!
4219endfunc
4220
4221func Test_lbuffer_with_bwipe()
4222  new
4223  new
4224  augroup nasty
4225    au QuickFixCmdPre,QuickFixCmdPost,BufEnter,BufLeave * bwipe
4226  augroup END
4227  lbuffer
4228  augroup nasty
4229    au!
4230  augroup END
4231endfunc
4232
4233" Test for an autocmd freeing the quickfix/location list when cexpr/lexpr is
4234" running
4235func Xexpr_acmd_freelist(cchar)
4236  call s:setup_commands(a:cchar)
4237
4238  " This was using freed memory (but with what events?)
4239  augroup nasty
4240    au QuickFixCmdPre,QuickFixCmdPost,BufEnter,BufLeave * call g:Xsetlist([], 'f')
4241  augroup END
4242  Xexpr "x"
4243  augroup nasty
4244    au!
4245  augroup END
4246endfunc
4247
4248func Test_cexpr_acmd_freelist()
4249  call Xexpr_acmd_freelist('c')
4250  call Xexpr_acmd_freelist('l')
4251endfunc
4252
4253" Test for commands that create a new quickfix/location list and jump to the
4254" first error automatically.
4255func Xjumpto_first_error_test(cchar)
4256  call s:setup_commands(a:cchar)
4257
4258  call s:create_test_file('Xtestfile1')
4259  call s:create_test_file('Xtestfile2')
4260  let l = ['Xtestfile1:2:Line2', 'Xtestfile2:4:Line4']
4261
4262  " Test for cexpr/lexpr
4263  enew
4264  Xexpr l
4265  call assert_equal('Xtestfile1', @%)
4266  call assert_equal(2, line('.'))
4267
4268  " Test for cfile/lfile
4269  enew
4270  call writefile(l, 'Xerr')
4271  Xfile Xerr
4272  call assert_equal('Xtestfile1', @%)
4273  call assert_equal(2, line('.'))
4274
4275  " Test for cbuffer/lbuffer
4276  edit Xerr
4277  Xbuffer
4278  call assert_equal('Xtestfile1', @%)
4279  call assert_equal(2, line('.'))
4280
4281  call delete('Xerr')
4282  call delete('Xtestfile1')
4283  call delete('Xtestfile2')
4284endfunc
4285
4286func Test_jumpto_first_error()
4287  call Xjumpto_first_error_test('c')
4288  call Xjumpto_first_error_test('l')
4289endfunc
4290
4291" Test for a quickfix autocmd changing the quickfix/location list before
4292" jumping to the first error in the new list.
4293func Xautocmd_changelist(cchar)
4294  call s:setup_commands(a:cchar)
4295
4296  " Test for cfile/lfile
4297  call s:create_test_file('Xtestfile1')
4298  call s:create_test_file('Xtestfile2')
4299  Xexpr 'Xtestfile1:2:Line2'
4300  autocmd QuickFixCmdPost * Xolder
4301  call writefile(['Xtestfile2:4:Line4'], 'Xerr')
4302  Xfile Xerr
4303  call assert_equal('Xtestfile2', @%)
4304  call assert_equal(4, line('.'))
4305  autocmd! QuickFixCmdPost
4306
4307  " Test for cbuffer/lbuffer
4308  call g:Xsetlist([], 'f')
4309  Xexpr 'Xtestfile1:2:Line2'
4310  autocmd QuickFixCmdPost * Xolder
4311  call writefile(['Xtestfile2:4:Line4'], 'Xerr')
4312  edit Xerr
4313  Xbuffer
4314  call assert_equal('Xtestfile2', @%)
4315  call assert_equal(4, line('.'))
4316  autocmd! QuickFixCmdPost
4317
4318  " Test for cexpr/lexpr
4319  call g:Xsetlist([], 'f')
4320  Xexpr 'Xtestfile1:2:Line2'
4321  autocmd QuickFixCmdPost * Xolder
4322  Xexpr 'Xtestfile2:4:Line4'
4323  call assert_equal('Xtestfile2', @%)
4324  call assert_equal(4, line('.'))
4325  autocmd! QuickFixCmdPost
4326
4327  " The grepprg may not be set on non-Unix systems
4328  if has('unix')
4329    " Test for grep/lgrep
4330    call g:Xsetlist([], 'f')
4331    Xexpr 'Xtestfile1:2:Line2'
4332    autocmd QuickFixCmdPost * Xolder
4333    silent Xgrep Line5 Xtestfile2
4334    call assert_equal('Xtestfile2', @%)
4335    call assert_equal(5, line('.'))
4336    autocmd! QuickFixCmdPost
4337  endif
4338
4339  " Test for vimgrep/lvimgrep
4340  call g:Xsetlist([], 'f')
4341  Xexpr 'Xtestfile1:2:Line2'
4342  autocmd QuickFixCmdPost * Xolder
4343  silent Xvimgrep Line5 Xtestfile2
4344  call assert_equal('Xtestfile2', @%)
4345  call assert_equal(5, line('.'))
4346  autocmd! QuickFixCmdPost
4347
4348  " Test for autocommands clearing the quickfix list before jumping to the
4349  " first error. This should not result in an error
4350  autocmd QuickFixCmdPost * call g:Xsetlist([], 'r')
4351  let v:errmsg = ''
4352  " Test for cfile/lfile
4353  Xfile Xerr
4354  call assert_true(v:errmsg !~# 'E42:')
4355  " Test for cbuffer/lbuffer
4356  edit Xerr
4357  Xbuffer
4358  call assert_true(v:errmsg !~# 'E42:')
4359  " Test for cexpr/lexpr
4360  Xexpr 'Xtestfile2:4:Line4'
4361  call assert_true(v:errmsg !~# 'E42:')
4362  " Test for grep/lgrep
4363  " The grepprg may not be set on non-Unix systems
4364  if has('unix')
4365    silent Xgrep Line5 Xtestfile2
4366    call assert_true(v:errmsg !~# 'E42:')
4367  endif
4368  " Test for vimgrep/lvimgrep
4369  call assert_fails('silent Xvimgrep Line5 Xtestfile2', 'E480:')
4370  autocmd! QuickFixCmdPost
4371
4372  call delete('Xerr')
4373  call delete('Xtestfile1')
4374  call delete('Xtestfile2')
4375endfunc
4376
4377func Test_autocmd_changelist()
4378  call Xautocmd_changelist('c')
4379  call Xautocmd_changelist('l')
4380endfunc
4381
4382" Tests for the ':filter /pat/ clist' command
4383func Test_filter_clist()
4384  cexpr ['Xfile1:10:10:Line 10', 'Xfile2:15:15:Line 15']
4385  call assert_equal([' 2 Xfile2:15 col 15: Line 15'],
4386			\ split(execute('filter /Line 15/ clist'), "\n"))
4387  call assert_equal([' 1 Xfile1:10 col 10: Line 10'],
4388			\ split(execute('filter /Xfile1/ clist'), "\n"))
4389  call assert_equal([], split(execute('filter /abc/ clist'), "\n"))
4390
4391  call setqflist([{'module' : 'abc', 'pattern' : 'pat1'},
4392			\ {'module' : 'pqr', 'pattern' : 'pat2'}], ' ')
4393  call assert_equal([' 2 pqr:pat2:  '],
4394			\ split(execute('filter /pqr/ clist'), "\n"))
4395  call assert_equal([' 1 abc:pat1:  '],
4396			\ split(execute('filter /pat1/ clist'), "\n"))
4397endfunc
4398
4399" Tests for the "CTRL-W <CR>" command.
4400func Xview_result_split_tests(cchar)
4401  call s:setup_commands(a:cchar)
4402
4403  " Test that "CTRL-W <CR>" in a qf/ll window fails with empty list.
4404  call g:Xsetlist([])
4405  Xopen
4406  let l:win_count = winnr('$')
4407  call assert_fails('execute "normal! \<C-W>\<CR>"', 'E42:')
4408  call assert_equal(l:win_count, winnr('$'))
4409  Xclose
4410endfunc
4411
4412func Test_view_result_split()
4413  call Xview_result_split_tests('c')
4414  call Xview_result_split_tests('l')
4415endfunc
4416
4417" Test that :cc sets curswant
4418func Test_curswant()
4419  helpgrep quickfix
4420  normal! llll
4421  1cc
4422  call assert_equal(getcurpos()[4], virtcol('.'))
4423  cclose | helpclose
4424endfunc
4425
4426" Test for opening a file from the quickfix window using CTRL-W <Enter>
4427" doesn't leave an empty buffer around.
4428func Test_splitview()
4429  call s:create_test_file('Xtestfile1')
4430  call s:create_test_file('Xtestfile2')
4431  new | only
4432  let last_bufnr = bufnr('Test_sv_1', 1)
4433  let l = ['Xtestfile1:2:Line2', 'Xtestfile2:4:Line4']
4434  cgetexpr l
4435  copen
4436  let numbufs = len(getbufinfo())
4437  exe "normal \<C-W>\<CR>"
4438  copen
4439  exe "normal j\<C-W>\<CR>"
4440  " Make sure new empty buffers are not created
4441  call assert_equal(numbufs, len(getbufinfo()))
4442  " Creating a new buffer should use the next available buffer number
4443  call assert_equal(last_bufnr + 4, bufnr("Test_sv_2", 1))
4444  bwipe Test_sv_1
4445  bwipe Test_sv_2
4446  new | only
4447
4448  " When split opening files from location list window, make sure that two
4449  " windows doesn't refer to the same location list
4450  lgetexpr l
4451  let locid = getloclist(0, {'id' : 0}).id
4452  lopen
4453  exe "normal \<C-W>\<CR>"
4454  call assert_notequal(locid, getloclist(0, {'id' : 0}).id)
4455  call assert_equal(0, getloclist(0, {'winid' : 0}).winid)
4456  new | only
4457
4458  " When split opening files from a helpgrep location list window, a new help
4459  " window should be opened with a copy of the location list.
4460  lhelpgrep window
4461  let locid = getloclist(0, {'id' : 0}).id
4462  lwindow
4463  exe "normal j\<C-W>\<CR>"
4464  call assert_notequal(locid, getloclist(0, {'id' : 0}).id)
4465  call assert_equal(0, getloclist(0, {'winid' : 0}).winid)
4466  new | only
4467
4468  " Using :split or :vsplit from a quickfix window should behave like a :new
4469  " or a :vnew command
4470  copen
4471  split
4472  call assert_equal(3, winnr('$'))
4473  let l = getwininfo()
4474  call assert_equal([0, 0, 1], [l[0].quickfix, l[1].quickfix, l[2].quickfix])
4475  close
4476  copen
4477  vsplit
4478  let l = getwininfo()
4479  call assert_equal([0, 0, 1], [l[0].quickfix, l[1].quickfix, l[2].quickfix])
4480  new | only
4481
4482  call delete('Xtestfile1')
4483  call delete('Xtestfile2')
4484endfunc
4485
4486" Test for parsing entries using visual screen column
4487func Test_viscol()
4488  enew
4489  call writefile(["Col1\tCol2\tCol3"], 'Xfile1')
4490  edit Xfile1
4491
4492  " Use byte offset for column number
4493  set efm&
4494  cexpr "Xfile1:1:5:XX\nXfile1:1:9:YY\nXfile1:1:20:ZZ"
4495  call assert_equal([5, 8], [col('.'), virtcol('.')])
4496  cnext
4497  call assert_equal([9, 12], [col('.'), virtcol('.')])
4498  cnext
4499  call assert_equal([14, 20], [col('.'), virtcol('.')])
4500
4501  " Use screen column offset for column number
4502  set efm=%f:%l:%v:%m
4503  cexpr "Xfile1:1:8:XX\nXfile1:1:12:YY\nXfile1:1:20:ZZ"
4504  call assert_equal([5, 8], [col('.'), virtcol('.')])
4505  cnext
4506  call assert_equal([9, 12], [col('.'), virtcol('.')])
4507  cnext
4508  call assert_equal([14, 20], [col('.'), virtcol('.')])
4509  cexpr "Xfile1:1:6:XX\nXfile1:1:15:YY\nXfile1:1:24:ZZ"
4510  call assert_equal([5, 8], [col('.'), virtcol('.')])
4511  cnext
4512  call assert_equal([10, 16], [col('.'), virtcol('.')])
4513  cnext
4514  call assert_equal([14, 20], [col('.'), virtcol('.')])
4515
4516  enew
4517  call writefile(["Col1\täü\töß\tCol4"], 'Xfile1')
4518
4519  " Use byte offset for column number
4520  set efm&
4521  cexpr "Xfile1:1:8:XX\nXfile1:1:11:YY\nXfile1:1:16:ZZ"
4522  call assert_equal([8, 10], [col('.'), virtcol('.')])
4523  cnext
4524  call assert_equal([11, 17], [col('.'), virtcol('.')])
4525  cnext
4526  call assert_equal([16, 25], [col('.'), virtcol('.')])
4527
4528  " Use screen column offset for column number
4529  set efm=%f:%l:%v:%m
4530  cexpr "Xfile1:1:10:XX\nXfile1:1:17:YY\nXfile1:1:25:ZZ"
4531  call assert_equal([8, 10], [col('.'), virtcol('.')])
4532  cnext
4533  call assert_equal([11, 17], [col('.'), virtcol('.')])
4534  cnext
4535  call assert_equal([16, 25], [col('.'), virtcol('.')])
4536
4537  " Use screen column number with a multi-line error message
4538  enew
4539  call writefile(["à test"], 'Xfile1')
4540  set efm=%E===\ %f\ ===,%C%l:%v,%Z%m
4541  cexpr ["=== Xfile1 ===", "1:3", "errormsg"]
4542  call assert_equal('Xfile1', @%)
4543  call assert_equal([0, 1, 4, 0], getpos('.'))
4544
4545  " Repeat previous test with byte offset %c: ensure that fix to issue #7145
4546  " does not break this
4547  set efm=%E===\ %f\ ===,%C%l:%c,%Z%m
4548  cexpr ["=== Xfile1 ===", "1:3", "errormsg"]
4549  call assert_equal('Xfile1', @%)
4550  call assert_equal([0, 1, 3, 0], getpos('.'))
4551
4552  enew | only
4553  set efm&
4554  call delete('Xfile1')
4555endfunc
4556
4557" Test for the quickfix window buffer
4558func Xqfbuf_test(cchar)
4559  call s:setup_commands(a:cchar)
4560
4561  " Quickfix buffer should be reused across closing and opening a quickfix
4562  " window
4563  Xexpr "F1:10:Line10"
4564  Xopen
4565  let qfbnum = bufnr('')
4566  Xclose
4567  " Even after the quickfix window is closed, the buffer should be loaded
4568  call assert_true(bufloaded(qfbnum))
4569  call assert_true(qfbnum, g:Xgetlist({'qfbufnr' : 0}).qfbufnr)
4570  Xopen
4571  " Buffer should be reused when opening the window again
4572  call assert_equal(qfbnum, bufnr(''))
4573  Xclose
4574
4575  if a:cchar == 'l'
4576    %bwipe
4577    " For a location list, when both the file window and the location list
4578    " window for the list are closed, then the buffer should be freed.
4579    new | only
4580    lexpr "F1:10:Line10"
4581    let wid = win_getid()
4582    lopen
4583    let qfbnum = bufnr('')
4584    call assert_match(qfbnum . ' %a-  "\[Location List]"', execute('ls'))
4585    close
4586    " When the location list window is closed, the buffer name should not
4587    " change to 'Quickfix List'
4588    call assert_match(qfbnum . 'u h-  "\[Location List]"', execute('ls!'))
4589    call assert_true(bufloaded(qfbnum))
4590
4591    " After deleting a location list buffer using ":bdelete", opening the
4592    " location list window should mark the buffer as a location list buffer.
4593    exe "bdelete " . qfbnum
4594    lopen
4595    call assert_equal("quickfix", &buftype)
4596    call assert_equal(1, getwininfo(win_getid(winnr()))[0].loclist)
4597    call assert_equal(wid, getloclist(0, {'filewinid' : 0}).filewinid)
4598    call assert_false(&swapfile)
4599    lclose
4600
4601    " When the location list is cleared for the window, the buffer should be
4602    " removed
4603    call setloclist(0, [], 'f')
4604    call assert_false(bufexists(qfbnum))
4605    call assert_equal(0, getloclist(0, {'qfbufnr' : 0}).qfbufnr)
4606
4607    " When the location list is freed with the location list window open, the
4608    " location list buffer should not be lost. It should be reused when the
4609    " location list is again populated.
4610    lexpr "F1:10:Line10"
4611    lopen
4612    let wid = win_getid()
4613    let qfbnum = bufnr('')
4614    wincmd p
4615    call setloclist(0, [], 'f')
4616    lexpr "F1:10:Line10"
4617    lopen
4618    call assert_equal(wid, win_getid())
4619    call assert_equal(qfbnum, bufnr(''))
4620    lclose
4621
4622    " When the window with the location list is closed, the buffer should be
4623    " removed
4624    new | only
4625    call assert_false(bufexists(qfbnum))
4626  endif
4627endfunc
4628
4629func Test_qfbuf()
4630  call Xqfbuf_test('c')
4631  call Xqfbuf_test('l')
4632endfunc
4633
4634" If there is an autocmd to use only one window, then opening the location
4635" list window used to crash Vim.
4636func Test_winonly_autocmd()
4637  call s:create_test_file('Xtest1')
4638  " Autocmd to show only one Vim window at a time
4639  autocmd WinEnter * only
4640  new
4641  " Load the location list
4642  lexpr "Xtest1:5:Line5\nXtest1:10:Line10\nXtest1:15:Line15"
4643  let loclistid = getloclist(0, {'id' : 0}).id
4644  " Open the location list window. Only this window will be shown and the file
4645  " window is closed.
4646  lopen
4647  call assert_equal(loclistid, getloclist(0, {'id' : 0}).id)
4648  " Jump to an entry in the location list and make sure that the cursor is
4649  " positioned correctly.
4650  ll 3
4651  call assert_equal(loclistid, getloclist(0, {'id' : 0}).id)
4652  call assert_equal('Xtest1', @%)
4653  call assert_equal(15, line('.'))
4654  " Cleanup
4655  autocmd! WinEnter
4656  new | only
4657  call delete('Xtest1')
4658endfunc
4659
4660" Test to make sure that an empty quickfix buffer is not reused for loading
4661" a normal buffer.
4662func Test_empty_qfbuf()
4663  enew | only
4664  call writefile(["Test"], 'Xfile1')
4665  call setqflist([], 'f')
4666  copen | only
4667  let qfbuf = bufnr('')
4668  edit Xfile1
4669  call assert_notequal(qfbuf, bufnr(''))
4670  enew
4671  call delete('Xfile1')
4672endfunc
4673
4674" Test for the :cbelow, :cabove, :lbelow and :labove commands.
4675" And for the :cafter, :cbefore, :lafter and :lbefore commands.
4676func Xtest_below(cchar)
4677  call s:setup_commands(a:cchar)
4678
4679  " No quickfix/location list
4680  call assert_fails('Xbelow', 'E42:')
4681  call assert_fails('Xabove', 'E42:')
4682  call assert_fails('Xbefore', 'E42:')
4683  call assert_fails('Xafter', 'E42:')
4684
4685  " Empty quickfix/location list
4686  call g:Xsetlist([])
4687  call assert_fails('Xbelow', 'E42:')
4688  call assert_fails('Xabove', 'E42:')
4689  call assert_fails('Xbefore', 'E42:')
4690  call assert_fails('Xafter', 'E42:')
4691
4692  call s:create_test_file('X1')
4693  call s:create_test_file('X2')
4694  call s:create_test_file('X3')
4695  call s:create_test_file('X4')
4696
4697  " Invalid entries
4698  edit X1
4699  call g:Xsetlist(["E1", "E2"])
4700  call assert_fails('Xbelow', 'E42:')
4701  call assert_fails('Xabove', 'E42:')
4702  call assert_fails('3Xbelow', 'E42:')
4703  call assert_fails('4Xabove', 'E42:')
4704  call assert_fails('Xbefore', 'E42:')
4705  call assert_fails('Xafter', 'E42:')
4706  call assert_fails('3Xbefore', 'E42:')
4707  call assert_fails('4Xafter', 'E42:')
4708
4709  " Test the commands with various arguments
4710  Xexpr ["X1:5:3:L5", "X2:5:2:L5", "X2:10:3:L10", "X2:15:4:L15", "X3:3:5:L3"]
4711  edit +7 X2
4712  Xabove
4713  call assert_equal(['X2', 5], [@%, line('.')])
4714  call assert_fails('Xabove', 'E553:')
4715  normal 7G
4716  Xbefore
4717  call assert_equal(['X2', 5, 2], [@%, line('.'), col('.')])
4718  call assert_fails('Xbefore', 'E553:')
4719
4720  normal 2j
4721  Xbelow
4722  call assert_equal(['X2', 10], [@%, line('.')])
4723  normal 7G
4724  Xafter
4725  call assert_equal(['X2', 10, 3], [@%, line('.'), col('.')])
4726
4727  " Last error in this file
4728  Xbelow 99
4729  call assert_equal(['X2', 15], [@%, line('.')])
4730  call assert_fails('Xbelow', 'E553:')
4731  normal gg
4732  Xafter 99
4733  call assert_equal(['X2', 15, 4], [@%, line('.'), col('.')])
4734  call assert_fails('Xafter', 'E553:')
4735
4736  " First error in this file
4737  Xabove 99
4738  call assert_equal(['X2', 5], [@%, line('.')])
4739  call assert_fails('Xabove', 'E553:')
4740  normal G
4741  Xbefore 99
4742  call assert_equal(['X2', 5, 2], [@%, line('.'), col('.')])
4743  call assert_fails('Xbefore', 'E553:')
4744
4745  normal gg
4746  Xbelow 2
4747  call assert_equal(['X2', 10], [@%, line('.')])
4748  normal gg
4749  Xafter 2
4750  call assert_equal(['X2', 10, 3], [@%, line('.'), col('.')])
4751
4752  normal G
4753  Xabove 2
4754  call assert_equal(['X2', 10], [@%, line('.')])
4755  normal G
4756  Xbefore 2
4757  call assert_equal(['X2', 10, 3], [@%, line('.'), col('.')])
4758
4759  edit X4
4760  call assert_fails('Xabove', 'E42:')
4761  call assert_fails('Xbelow', 'E42:')
4762  call assert_fails('Xbefore', 'E42:')
4763  call assert_fails('Xafter', 'E42:')
4764  if a:cchar == 'l'
4765    " If a buffer has location list entries from some other window but not
4766    " from the current window, then the commands should fail.
4767    edit X1 | split | call setloclist(0, [], 'f')
4768    call assert_fails('Xabove', 'E776:')
4769    call assert_fails('Xbelow', 'E776:')
4770    call assert_fails('Xbefore', 'E776:')
4771    call assert_fails('Xafter', 'E776:')
4772    close
4773  endif
4774
4775  " Test for lines with multiple quickfix entries
4776  Xexpr ["X1:5:L5", "X2:5:1:L5_1", "X2:5:2:L5_2", "X2:5:3:L5_3",
4777	      \ "X2:10:1:L10_1", "X2:10:2:L10_2", "X2:10:3:L10_3",
4778	      \ "X2:15:1:L15_1", "X2:15:2:L15_2", "X2:15:3:L15_3", "X3:3:L3"]
4779  edit +1 X2
4780  Xbelow 2
4781  call assert_equal(['X2', 10, 1], [@%, line('.'), col('.')])
4782  normal 1G
4783  Xafter 2
4784  call assert_equal(['X2', 5, 2], [@%, line('.'), col('.')])
4785
4786  normal gg
4787  Xbelow 99
4788  call assert_equal(['X2', 15, 1], [@%, line('.'), col('.')])
4789  normal gg
4790  Xafter 99
4791  call assert_equal(['X2', 15, 3], [@%, line('.'), col('.')])
4792
4793  normal G
4794  Xabove 2
4795  call assert_equal(['X2', 10, 1], [@%, line('.'), col('.')])
4796  normal G
4797  Xbefore 2
4798  call assert_equal(['X2', 15, 2], [@%, line('.'), col('.')])
4799
4800  normal G
4801  Xabove 99
4802  call assert_equal(['X2', 5, 1], [@%, line('.'), col('.')])
4803  normal G
4804  Xbefore 99
4805  call assert_equal(['X2', 5, 1], [@%, line('.'), col('.')])
4806
4807  normal 10G
4808  Xabove
4809  call assert_equal(['X2', 5, 1], [@%, line('.'), col('.')])
4810  normal 10G$
4811  2Xbefore
4812  call assert_equal(['X2', 10, 2], [@%, line('.'), col('.')])
4813
4814  normal 10G
4815  Xbelow
4816  call assert_equal(['X2', 15, 1], [@%, line('.'), col('.')])
4817  normal 9G
4818  5Xafter
4819  call assert_equal(['X2', 15, 2], [@%, line('.'), col('.')])
4820
4821  " Invalid range
4822  if a:cchar == 'c'
4823    call assert_fails('-2cbelow', 'E16:')
4824    call assert_fails('-2cafter', 'E16:')
4825  else
4826    call assert_fails('-2lbelow', 'E16:')
4827    call assert_fails('-2lafter', 'E16:')
4828  endif
4829
4830  call delete('X1')
4831  call delete('X2')
4832  call delete('X3')
4833  call delete('X4')
4834endfunc
4835
4836func Test_cbelow()
4837  call Xtest_below('c')
4838  call Xtest_below('l')
4839endfunc
4840
4841func Test_quickfix_count()
4842  let commands = [
4843	\ 'cNext',
4844	\ 'cNfile',
4845	\ 'cabove',
4846	\ 'cbelow',
4847	\ 'cfirst',
4848	\ 'clast',
4849	\ 'cnewer',
4850	\ 'cnext',
4851	\ 'cnfile',
4852	\ 'colder',
4853	\ 'cprevious',
4854	\ 'crewind',
4855	\
4856	\ 'lNext',
4857	\ 'lNfile',
4858	\ 'labove',
4859	\ 'lbelow',
4860	\ 'lfirst',
4861	\ 'llast',
4862	\ 'lnewer',
4863	\ 'lnext',
4864	\ 'lnfile',
4865	\ 'lolder',
4866	\ 'lprevious',
4867	\ 'lrewind',
4868	\ ]
4869  for cmd in commands
4870    call assert_fails('-1' .. cmd, 'E16:')
4871    call assert_fails('.' .. cmd, 'E16:')
4872    call assert_fails('%' .. cmd, 'E16:')
4873    call assert_fails('$' .. cmd, 'E16:')
4874  endfor
4875endfunc
4876
4877" Test for aborting quickfix commands using QuickFixCmdPre
4878func Xtest_qfcmd_abort(cchar)
4879  call s:setup_commands(a:cchar)
4880
4881  call g:Xsetlist([], 'f')
4882
4883  " cexpr/lexpr
4884  let e = ''
4885  try
4886    Xexpr ["F1:10:Line10", "F2:20:Line20"]
4887  catch /.*/
4888    let e = v:exception
4889  endtry
4890  call assert_equal('AbortCmd', e)
4891  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4892
4893  " cfile/lfile
4894  call writefile(["F1:10:Line10", "F2:20:Line20"], 'Xfile1')
4895  let e = ''
4896  try
4897    Xfile Xfile1
4898  catch /.*/
4899    let e = v:exception
4900  endtry
4901  call assert_equal('AbortCmd', e)
4902  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4903  call delete('Xfile1')
4904
4905  " cgetbuffer/lgetbuffer
4906  enew!
4907  call append(0, ["F1:10:Line10", "F2:20:Line20"])
4908  let e = ''
4909  try
4910    Xgetbuffer
4911  catch /.*/
4912    let e = v:exception
4913  endtry
4914  call assert_equal('AbortCmd', e)
4915  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4916  enew!
4917
4918  " vimgrep/lvimgrep
4919  let e = ''
4920  try
4921    Xvimgrep /func/ test_quickfix.vim
4922  catch /.*/
4923    let e = v:exception
4924  endtry
4925  call assert_equal('AbortCmd', e)
4926  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4927
4928  " helpgrep/lhelpgrep
4929  let e = ''
4930  try
4931    Xhelpgrep quickfix
4932  catch /.*/
4933    let e = v:exception
4934  endtry
4935  call assert_equal('AbortCmd', e)
4936  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4937
4938  " grep/lgrep
4939  if has('unix')
4940    let e = ''
4941    try
4942      silent Xgrep func test_quickfix.vim
4943    catch /.*/
4944      let e = v:exception
4945    endtry
4946    call assert_equal('AbortCmd', e)
4947    call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4948  endif
4949endfunc
4950
4951func Test_qfcmd_abort()
4952  augroup QF_Test
4953    au!
4954    autocmd  QuickFixCmdPre * throw "AbortCmd"
4955  augroup END
4956
4957  call Xtest_qfcmd_abort('c')
4958  call Xtest_qfcmd_abort('l')
4959
4960  augroup QF_Test
4961    au!
4962  augroup END
4963endfunc
4964
4965" Test for using a file in one of the parent directories.
4966func Test_search_in_dirstack()
4967  call mkdir('Xtestdir/a/b/c', 'p')
4968  let save_cwd = getcwd()
4969  call writefile(["X1_L1", "X1_L2"], 'Xtestdir/Xfile1')
4970  call writefile(["X2_L1", "X2_L2"], 'Xtestdir/a/Xfile2')
4971  call writefile(["X3_L1", "X3_L2"], 'Xtestdir/a/b/Xfile3')
4972  call writefile(["X4_L1", "X4_L2"], 'Xtestdir/a/b/c/Xfile4')
4973
4974  let lines = "Entering dir Xtestdir\n" .
4975	      \ "Entering dir a\n" .
4976	      \ "Entering dir b\n" .
4977	      \ "Xfile2:2:X2_L2\n" .
4978	      \ "Leaving dir a\n" .
4979	      \ "Xfile1:2:X1_L2\n" .
4980	      \ "Xfile3:1:X3_L1\n" .
4981	      \ "Entering dir c\n" .
4982	      \ "Xfile4:2:X4_L2\n" .
4983	      \ "Leaving dir c\n"
4984  set efm=%DEntering\ dir\ %f,%XLeaving\ dir\ %f,%f:%l:%m
4985  cexpr lines .. "Leaving dir Xtestdir|\n" | let next = 1
4986  call assert_equal(11, getqflist({'size' : 0}).size)
4987  call assert_equal(4, getqflist({'idx' : 0}).idx)
4988  call assert_equal('X2_L2', getline('.'))
4989  call assert_equal(1, next)
4990  cnext
4991  call assert_equal(6, getqflist({'idx' : 0}).idx)
4992  call assert_equal('X1_L2', getline('.'))
4993  cnext
4994  call assert_equal(7, getqflist({'idx' : 0}).idx)
4995  call assert_equal(1, line('$'))
4996  call assert_equal('', getline(1))
4997  cnext
4998  call assert_equal(9, getqflist({'idx' : 0}).idx)
4999  call assert_equal(1, line('$'))
5000  call assert_equal('', getline(1))
5001
5002  set efm&
5003  exe 'cd ' . save_cwd
5004  call delete('Xtestdir', 'rf')
5005endfunc
5006
5007" Test for :cquit
5008func Test_cquit()
5009  " Exit Vim with a non-zero value
5010  if RunVim([], ["cquit 7"], '')
5011    call assert_equal(7, v:shell_error)
5012  endif
5013
5014  if RunVim([], ["50cquit"], '')
5015    call assert_equal(50, v:shell_error)
5016  endif
5017
5018  " Exit Vim with default value
5019  if RunVim([], ["cquit"], '')
5020    call assert_equal(1, v:shell_error)
5021  endif
5022
5023  " Exit Vim with zero value
5024  if RunVim([], ["cquit 0"], '')
5025    call assert_equal(0, v:shell_error)
5026  endif
5027
5028  " Exit Vim with negative value
5029  call assert_fails('-3cquit', 'E16:')
5030endfunc
5031
5032" Test for getting a specific item from a quickfix list
5033func Xtest_getqflist_by_idx(cchar)
5034  call s:setup_commands(a:cchar)
5035  " Empty list
5036  call assert_equal([], g:Xgetlist({'idx' : 1, 'items' : 0}).items)
5037  Xexpr ['F1:10:L10', 'F1:20:L20']
5038  let l = g:Xgetlist({'idx' : 2, 'items' : 0}).items
5039  call assert_equal(bufnr('F1'), l[0].bufnr)
5040  call assert_equal(20, l[0].lnum)
5041  call assert_equal('L20', l[0].text)
5042  call assert_equal([], g:Xgetlist({'idx' : -1, 'items' : 0}).items)
5043  call assert_equal([], g:Xgetlist({'idx' : 3, 'items' : 0}).items)
5044  %bwipe!
5045endfunc
5046
5047func Test_getqflist_by_idx()
5048  call Xtest_getqflist_by_idx('c')
5049  call Xtest_getqflist_by_idx('l')
5050endfunc
5051
5052" Test for the 'quickfixtextfunc' setting
5053func Tqfexpr(info)
5054  if a:info.quickfix
5055    let qfl = getqflist({'id' : a:info.id, 'items' : 1}).items
5056  else
5057    let qfl = getloclist(a:info.winid, {'id' : a:info.id, 'items' : 1}).items
5058  endif
5059
5060  let l = []
5061  for idx in range(a:info.start_idx - 1, a:info.end_idx - 1)
5062    let e = qfl[idx]
5063    let s = ''
5064    if e.bufnr != 0
5065      let bname = bufname(e.bufnr)
5066      let s ..= fnamemodify(bname, ':.')
5067    endif
5068    let s ..= '-'
5069    let s ..= 'L' .. string(e.lnum) .. 'C' .. string(e.col) .. '-'
5070    let s ..= e.text
5071    call add(l, s)
5072  endfor
5073
5074  return l
5075endfunc
5076
5077func Xtest_qftextfunc(cchar)
5078  call s:setup_commands(a:cchar)
5079
5080  set efm=%f:%l:%c:%m
5081  set quickfixtextfunc=Tqfexpr
5082  call assert_equal('Tqfexpr', &quickfixtextfunc)
5083  call assert_equal('',
5084        \ g:Xgetlist({'quickfixtextfunc' : 1}).quickfixtextfunc)
5085  Xexpr ['F1:10:2:green', 'F1:20:4:blue']
5086  Xwindow
5087  call assert_equal('F1-L10C2-green', getline(1))
5088  call assert_equal('F1-L20C4-blue', getline(2))
5089  Xclose
5090  set quickfixtextfunc&vim
5091  Xwindow
5092  call assert_equal('F1|10 col 2| green', getline(1))
5093  call assert_equal('F1|20 col 4| blue', getline(2))
5094  Xclose
5095  set efm&
5096  set quickfixtextfunc&
5097
5098  " Test for per list 'quickfixtextfunc' setting
5099  func PerQfText(info)
5100    if a:info.quickfix
5101      let qfl = getqflist({'id' : a:info.id, 'items' : 1}).items
5102    else
5103      let qfl = getloclist(a:info.winid, {'id' : a:info.id, 'items' : 1}).items
5104    endif
5105    if empty(qfl)
5106      return []
5107    endif
5108    let l = []
5109    for idx in range(a:info.start_idx - 1, a:info.end_idx - 1)
5110      call add(l, 'Line ' .. qfl[idx].lnum .. ', Col ' .. qfl[idx].col)
5111    endfor
5112    return l
5113  endfunc
5114  set quickfixtextfunc=Tqfexpr
5115  call g:Xsetlist([], ' ', {'quickfixtextfunc' : "PerQfText"})
5116  Xaddexpr ['F1:10:2:green', 'F1:20:4:blue']
5117  Xwindow
5118  call assert_equal('Line 10, Col 2', getline(1))
5119  call assert_equal('Line 20, Col 4', getline(2))
5120  Xclose
5121  call assert_equal(function('PerQfText'),
5122        \ g:Xgetlist({'quickfixtextfunc' : 1}).quickfixtextfunc)
5123  " Add entries to the list when the quickfix buffer is hidden
5124  Xaddexpr ['F1:30:6:red']
5125  Xwindow
5126  call assert_equal('Line 30, Col 6', getline(3))
5127  Xclose
5128  call g:Xsetlist([], 'r', {'quickfixtextfunc' : ''})
5129  call assert_equal('', g:Xgetlist({'quickfixtextfunc' : 1}).quickfixtextfunc)
5130  set quickfixtextfunc&
5131  delfunc PerQfText
5132
5133  " Non-existing function
5134  set quickfixtextfunc=Tabc
5135  call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue']", 'E117:')
5136  call assert_fails("Xwindow", 'E117:')
5137  Xclose
5138  set quickfixtextfunc&
5139
5140  " set option to a non-function
5141  set quickfixtextfunc=[10,\ 20]
5142  call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue']", 'E117:')
5143  call assert_fails("Xwindow", 'E117:')
5144  Xclose
5145  set quickfixtextfunc&
5146
5147  " set option to a function with different set of arguments
5148  func Xqftext(a, b, c)
5149    return a:a .. a:b .. a:c
5150  endfunc
5151  set quickfixtextfunc=Xqftext
5152  call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue']", 'E119:')
5153  call assert_fails("Xwindow", 'E119:')
5154  Xclose
5155
5156  " set option to a function that returns a list with non-strings
5157  func Xqftext2(d)
5158    return ['one', [], 'two']
5159  endfunc
5160  set quickfixtextfunc=Xqftext2
5161  call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue', 'F1:30:6:red']",
5162                                                                  \ 'E730:')
5163  call assert_fails('Xwindow', 'E730:')
5164  call assert_equal(['one', 'F1|20 col 4| blue', 'F1|30 col 6| red'],
5165        \ getline(1, '$'))
5166  Xclose
5167
5168  set quickfixtextfunc&
5169  delfunc Xqftext
5170  delfunc Xqftext2
5171
5172  " set the global option to a lambda function
5173  set quickfixtextfunc={d\ ->\ map(g:Xgetlist({'id'\ :\ d.id,\ 'items'\ :\ 1}).items[d.start_idx-1:d.end_idx-1],\ 'v:val.text')}
5174  Xexpr ['F1:10:2:green', 'F1:20:4:blue']
5175  Xwindow
5176  call assert_equal(['green', 'blue'], getline(1, '$'))
5177  Xclose
5178  call assert_equal("{d -> map(g:Xgetlist({'id' : d.id, 'items' : 1}).items[d.start_idx-1:d.end_idx-1], 'v:val.text')}", &quickfixtextfunc)
5179  set quickfixtextfunc&
5180
5181  " use a lambda function that returns an empty list
5182  set quickfixtextfunc={d\ ->\ []}
5183  Xexpr ['F1:10:2:green', 'F1:20:4:blue']
5184  Xwindow
5185  call assert_equal(['F1|10 col 2| green', 'F1|20 col 4| blue'],
5186        \ getline(1, '$'))
5187  Xclose
5188  set quickfixtextfunc&
5189
5190  " use a lambda function that returns a list with empty strings
5191  set quickfixtextfunc={d\ ->\ ['',\ '']}
5192  Xexpr ['F1:10:2:green', 'F1:20:4:blue']
5193  Xwindow
5194  call assert_equal(['F1|10 col 2| green', 'F1|20 col 4| blue'],
5195        \ getline(1, '$'))
5196  Xclose
5197  set quickfixtextfunc&
5198
5199  " set the per-quickfix list text function to a lambda function
5200  call g:Xsetlist([], ' ',
5201        \ {'quickfixtextfunc' :
5202        \   {d -> map(g:Xgetlist({'id' : d.id, 'items' : 1}).items[d.start_idx-1:d.end_idx-1],
5203        \ "'Line ' .. v:val.lnum .. ', Col ' .. v:val.col")}})
5204  Xaddexpr ['F1:10:2:green', 'F1:20:4:blue']
5205  Xwindow
5206  call assert_equal('Line 10, Col 2', getline(1))
5207  call assert_equal('Line 20, Col 4', getline(2))
5208  Xclose
5209  call assert_match("function('<lambda>\\d\\+')", string(g:Xgetlist({'quickfixtextfunc' : 1}).quickfixtextfunc))
5210  call g:Xsetlist([], 'f')
5211endfunc
5212
5213func Test_qftextfunc()
5214  call Xtest_qftextfunc('c')
5215  call Xtest_qftextfunc('l')
5216endfunc
5217
5218" Running :lhelpgrep command more than once in a help window, doesn't jump to
5219" the help topic
5220func Test_lhelpgrep_from_help_window()
5221  call mkdir('Xtestdir/doc', 'p')
5222  call writefile(['window'], 'Xtestdir/doc/a.txt')
5223  call writefile(['buffer'], 'Xtestdir/doc/b.txt')
5224  let save_rtp = &rtp
5225  let &rtp = 'Xtestdir'
5226  lhelpgrep window
5227  lhelpgrep buffer
5228  call assert_equal('b.txt', fnamemodify(@%, ":p:t"))
5229  lhelpgrep window
5230  call assert_equal('a.txt', fnamemodify(@%, ":p:t"))
5231  let &rtp = save_rtp
5232  call delete('Xtestdir', 'rf')
5233  new | only!
5234endfunc
5235
5236" Test for the crash fixed by 7.3.715
5237func Test_setloclist_crash()
5238  %bw!
5239  let g:BufNum = bufnr()
5240  augroup QF_Test
5241    au!
5242    au BufUnload * call setloclist(0, [{'bufnr':g:BufNum, 'lnum':1, 'col':1, 'text': 'tango down'}])
5243  augroup END
5244
5245  try
5246    lvimgrep /.*/ *.mak
5247  catch /E926:/
5248  endtry
5249  call assert_equal('tango down', getloclist(0, {'items' : 0}).items[0].text)
5250  call assert_equal(1, getloclist(0, {'size' : 0}).size)
5251
5252  augroup QF_Test
5253    au!
5254  augroup END
5255  unlet g:BufNum
5256  %bw!
5257endfunc
5258
5259" Test for adding an invalid entry with the quickfix window open and making
5260" sure that the window contents are not changed
5261func Test_add_invalid_entry_with_qf_window()
5262  call setqflist([], 'f')
5263  cexpr "Xfile1:10:aa"
5264  copen
5265  call setqflist(['bb'], 'a')
5266  call assert_equal(1, line('$'))
5267  call assert_equal(['Xfile1|10| aa'], getline(1, '$'))
5268  call assert_equal([{'lnum': 10, 'bufnr': bufnr('Xfile1'), 'col': 0, 'pattern': '', 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'module': '', 'text': 'aa'}], getqflist())
5269  cclose
5270endfunc
5271
5272" Test for very weird problem: autocommand causes a failure, resulting opening
5273" the quickfix window to fail. This still splits the window, but otherwise
5274" should not mess up buffers.
5275func Test_quickfix_window_fails_to_open()
5276  CheckScreendump
5277
5278  let lines =<< trim END
5279      anything
5280      try
5281        anything
5282      endtry
5283  END
5284  call writefile(lines, 'XquickfixFails')
5285
5286  let lines =<< trim END
5287      split XquickfixFails
5288      silent vimgrep anything %
5289      normal o
5290      au BufLeave * ++once source XquickfixFails
5291      " This will trigger the autocommand, which causes an error, what follows
5292      " is aborted but the window was already split.
5293      silent! cwindow
5294  END
5295  call writefile(lines, 'XtestWinFails')
5296  let buf = RunVimInTerminal('-S XtestWinFails', #{rows: 13})
5297  call VerifyScreenDump(buf, 'Test_quickfix_window_fails', {})
5298
5299  " clean up
5300  call term_sendkeys(buf, ":bwipe!\<CR>")
5301  call term_wait(buf)
5302  call StopVimInTerminal(buf)
5303  call delete('XtestWinFails')
5304  call delete('XquickfixFails')
5305endfunc
5306
5307" Test for updating the quickfix buffer whenever the associated quickfix list
5308" is changed.
5309func Xqfbuf_update(cchar)
5310  call s:setup_commands(a:cchar)
5311
5312  Xexpr "F1:1:line1"
5313  Xopen
5314  call assert_equal(['F1|1| line1'], getline(1, '$'))
5315  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
5316
5317  " Test setqflist() using the 'lines' key in 'what'
5318  " add a new entry
5319  call g:Xsetlist([], 'a', {'lines' : ['F2:2: line2']})
5320  call assert_equal(['F1|1| line1', 'F2|2| line2'], getline(1, '$'))
5321  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
5322  " replace all the entries with a single entry
5323  call g:Xsetlist([], 'r', {'lines' : ['F3:3: line3']})
5324  call assert_equal(['F3|3| line3'], getline(1, '$'))
5325  call assert_equal(3, g:Xgetlist({'changedtick' : 0}).changedtick)
5326  " remove all the entries
5327  call g:Xsetlist([], 'r', {'lines' : []})
5328  call assert_equal([''], getline(1, '$'))
5329  call assert_equal(4, g:Xgetlist({'changedtick' : 0}).changedtick)
5330  " add a new list
5331  call g:Xsetlist([], ' ', {'lines' : ['F4:4: line4']})
5332  call assert_equal(['F4|4| line4'], getline(1, '$'))
5333  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
5334
5335  " Test setqflist() using the 'items' key in 'what'
5336  " add a new entry
5337  call g:Xsetlist([], 'a', {'items' : [{'filename' : 'F5', 'lnum' : 5, 'text' : 'line5'}]})
5338  call assert_equal(['F4|4| line4', 'F5|5| line5'], getline(1, '$'))
5339  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
5340  " replace all the entries with a single entry
5341  call g:Xsetlist([], 'r', {'items' : [{'filename' : 'F6', 'lnum' : 6, 'text' : 'line6'}]})
5342  call assert_equal(['F6|6| line6'], getline(1, '$'))
5343  call assert_equal(3, g:Xgetlist({'changedtick' : 0}).changedtick)
5344  " remove all the entries
5345  call g:Xsetlist([], 'r', {'items' : []})
5346  call assert_equal([''], getline(1, '$'))
5347  call assert_equal(4, g:Xgetlist({'changedtick' : 0}).changedtick)
5348  " add a new list
5349  call g:Xsetlist([], ' ', {'items' : [{'filename' : 'F7', 'lnum' : 7, 'text' : 'line7'}]})
5350  call assert_equal(['F7|7| line7'], getline(1, '$'))
5351  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
5352
5353  call g:Xsetlist([], ' ', {})
5354  call assert_equal([''], getline(1, '$'))
5355  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
5356
5357  Xclose
5358endfunc
5359
5360func Test_qfbuf_update()
5361  call Xqfbuf_update('c')
5362  call Xqfbuf_update('l')
5363endfunc
5364
5365" vim: shiftwidth=2 sts=2 expandtab
5366