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
2868" Test for incsearch highlighting of the :vimgrep pattern
2869" This test used to cause "E315: ml_get: invalid lnum" errors.
2870func Test_vimgrep_incsearch()
2871  enew
2872  set incsearch
2873  call test_override("char_avail", 1)
2874
2875  call feedkeys(":2vimgrep assert test_quickfix.vim test_cdo.vim\<CR>", "ntx")
2876  let l = getqflist()
2877  call assert_equal(2, len(l))
2878
2879  call test_override("ALL", 0)
2880  set noincsearch
2881endfunc
2882
2883" Test vimgrep with the last search pattern not set
2884func Test_vimgrep_with_no_last_search_pat()
2885  let lines =<< trim [SCRIPT]
2886    call assert_fails('vimgrep // *', 'E35:')
2887    call writefile(v:errors, 'Xresult')
2888    qall!
2889  [SCRIPT]
2890  call writefile(lines, 'Xscript')
2891  if RunVim([], [], '--clean -S Xscript')
2892    call assert_equal([], readfile('Xresult'))
2893  endif
2894  call delete('Xscript')
2895  call delete('Xresult')
2896endfunc
2897
2898" Test vimgrep without swap file
2899func Test_vimgrep_without_swap_file()
2900  let lines =<< trim [SCRIPT]
2901    vimgrep grep test_c*
2902    call writefile(['done'], 'Xresult')
2903    qall!
2904  [SCRIPT]
2905  call writefile(lines, 'Xscript')
2906  if RunVim([], [], '--clean -n -S Xscript Xscript')
2907    call assert_equal(['done'], readfile('Xresult'))
2908  endif
2909  call delete('Xscript')
2910  call delete('Xresult')
2911endfunc
2912
2913func Test_vimgrep_existing_swapfile()
2914  call writefile(['match apple with apple'], 'Xapple')
2915  call writefile(['swapfile'], '.Xapple.swp')
2916  let g:foundSwap = 0
2917  let g:ignoreSwapExists = 1
2918  augroup grep
2919    au SwapExists * let foundSwap = 1 | let v:swapchoice = 'e'
2920  augroup END
2921  vimgrep apple Xapple
2922  call assert_equal(1, g:foundSwap)
2923  call assert_match('.Xapple.swo', swapname(''))
2924
2925  call delete('Xapple')
2926  call delete('.Xapple.swp')
2927  augroup grep
2928    au! SwapExists
2929  augroup END
2930  unlet g:ignoreSwapExists
2931endfunc
2932
2933func XfreeTests(cchar)
2934  call s:setup_commands(a:cchar)
2935
2936  enew | only
2937
2938  " Deleting the quickfix stack should work even When the current list is
2939  " somewhere in the middle of the stack
2940  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2941  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2942  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2943  Xolder
2944  call g:Xsetlist([], 'f')
2945  call assert_equal(0, len(g:Xgetlist()))
2946
2947  " After deleting the stack, adding a new list should create a stack with a
2948  " single list.
2949  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2950  call assert_equal(1, g:Xgetlist({'all':1}).nr)
2951
2952  " Deleting the stack from a quickfix window should update/clear the
2953  " quickfix/location list window.
2954  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2955  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2956  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2957  Xolder
2958  Xwindow
2959  call g:Xsetlist([], 'f')
2960  call assert_equal(2, winnr('$'))
2961  call assert_equal(1, line('$'))
2962  Xclose
2963
2964  " Deleting the stack from a non-quickfix window should update/clear the
2965  " quickfix/location list window.
2966  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2967  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2968  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2969  Xolder
2970  Xwindow
2971  wincmd p
2972  call g:Xsetlist([], 'f')
2973  call assert_equal(0, len(g:Xgetlist()))
2974  wincmd p
2975  call assert_equal(2, winnr('$'))
2976  call assert_equal(1, line('$'))
2977
2978  " After deleting the location list stack, if the location list window is
2979  " opened, then a new location list should be created. So opening the
2980  " location list window again should not create a new window.
2981  if a:cchar == 'l'
2982      lexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2983      wincmd p
2984      lopen
2985      call assert_equal(2, winnr('$'))
2986  endif
2987  Xclose
2988endfunc
2989
2990" Tests for the quickfix free functionality
2991func Test_qf_free()
2992  call XfreeTests('c')
2993  call XfreeTests('l')
2994endfunc
2995
2996" Test for buffer overflow when parsing lines and adding new entries to
2997" the quickfix list.
2998func Test_bufoverflow()
2999  set efm=%f:%l:%m
3000  cgetexpr ['File1:100:' . repeat('x', 1025)]
3001
3002  set efm=%+GCompiler:\ %.%#,%f:%l:%m
3003  cgetexpr ['Compiler: ' . repeat('a', 1015), 'File1:10:Hello World']
3004
3005  set efm=%DEntering\ directory\ %f,%f:%l:%m
3006  cgetexpr ['Entering directory ' . repeat('a', 1006),
3007	      \ 'File1:10:Hello World']
3008  set efm&vim
3009endfunc
3010
3011" Tests for getting the quickfix stack size
3012func XsizeTests(cchar)
3013  call s:setup_commands(a:cchar)
3014
3015  call g:Xsetlist([], 'f')
3016  call assert_equal(0, g:Xgetlist({'nr':'$'}).nr)
3017  call assert_equal('', g:Xgetlist({'nr':'$', 'all':1}).title)
3018  call assert_equal(0, g:Xgetlist({'nr':0}).nr)
3019
3020  Xexpr "File1:10:Line1"
3021  Xexpr "File2:20:Line2"
3022  Xexpr "File3:30:Line3"
3023  Xolder | Xolder
3024  call assert_equal(3, g:Xgetlist({'nr':'$'}).nr)
3025  call g:Xsetlist([], 'f')
3026
3027  Xexpr "File1:10:Line1"
3028  Xexpr "File2:20:Line2"
3029  Xexpr "File3:30:Line3"
3030  Xolder | Xolder
3031  call g:Xsetlist([], 'a', {'nr':'$', 'title':'Compiler'})
3032  call assert_equal('Compiler', g:Xgetlist({'nr':3, 'all':1}).title)
3033endfunc
3034
3035func Test_Qf_Size()
3036  call XsizeTests('c')
3037  call XsizeTests('l')
3038endfunc
3039
3040func Test_cclose_from_copen()
3041    augroup QF_Test
3042	au!
3043        au FileType qf :call assert_fails(':cclose', 'E788:')
3044    augroup END
3045    copen
3046    augroup QF_Test
3047	au!
3048    augroup END
3049    augroup! QF_Test
3050endfunc
3051
3052func Test_cclose_in_autocmd()
3053  " Problem is only triggered if "starting" is zero, so that the OptionsSet
3054  " event will be triggered.
3055  call test_override('starting', 1)
3056  augroup QF_Test
3057    au!
3058    au FileType qf :call assert_fails(':cclose', 'E788:')
3059  augroup END
3060  copen
3061  augroup QF_Test
3062    au!
3063  augroup END
3064  augroup! QF_Test
3065  call test_override('starting', 0)
3066endfunc
3067
3068" Check that ":file" without an argument is possible even when "curbuf_lock"
3069" is set.
3070func Test_file_from_copen()
3071  " Works without argument.
3072  augroup QF_Test
3073    au!
3074    au FileType qf file
3075  augroup END
3076  copen
3077
3078  augroup QF_Test
3079    au!
3080  augroup END
3081  cclose
3082
3083  " Fails with argument.
3084  augroup QF_Test
3085    au!
3086    au FileType qf call assert_fails(':file foo', 'E788:')
3087  augroup END
3088  copen
3089  augroup QF_Test
3090    au!
3091  augroup END
3092  cclose
3093
3094  augroup! QF_Test
3095endfunc
3096
3097func Test_resize_from_copen()
3098  augroup QF_Test
3099    au!
3100    au FileType qf resize 5
3101  augroup END
3102  try
3103    " This should succeed without any exception.  No other buffers are
3104    " involved in the autocmd.
3105    copen
3106  finally
3107    augroup QF_Test
3108      au!
3109    augroup END
3110    augroup! QF_Test
3111  endtry
3112endfunc
3113
3114func Test_vimgrep_with_textlock()
3115  new
3116
3117  " Simple way to execute something with "textwinlock" set.
3118  " Check that vimgrep without jumping can be executed.
3119  au InsertCharPre * vimgrep /RunTheTest/j runtest.vim
3120  normal ax
3121  let qflist = getqflist()
3122  call assert_true(len(qflist) > 0)
3123  call assert_match('RunTheTest', qflist[0].text)
3124  call setqflist([], 'r')
3125  au! InsertCharPre
3126
3127  " Check that vimgrepadd without jumping can be executed.
3128  au InsertCharPre * vimgrepadd /RunTheTest/j runtest.vim
3129  normal ax
3130  let qflist = getqflist()
3131  call assert_true(len(qflist) > 0)
3132  call assert_match('RunTheTest', qflist[0].text)
3133  call setqflist([], 'r')
3134  au! InsertCharPre
3135
3136  " Check that lvimgrep without jumping can be executed.
3137  au InsertCharPre * lvimgrep /RunTheTest/j runtest.vim
3138  normal ax
3139  let qflist = getloclist(0)
3140  call assert_true(len(qflist) > 0)
3141  call assert_match('RunTheTest', qflist[0].text)
3142  call setloclist(0, [], 'r')
3143  au! InsertCharPre
3144
3145  " Check that lvimgrepadd without jumping can be executed.
3146  au InsertCharPre * lvimgrepadd /RunTheTest/j runtest.vim
3147  normal ax
3148  let qflist = getloclist(0)
3149  call assert_true(len(qflist) > 0)
3150  call assert_match('RunTheTest', qflist[0].text)
3151  call setloclist(0, [], 'r')
3152  au! InsertCharPre
3153
3154  " trying to jump will give an error
3155  au InsertCharPre * vimgrep /RunTheTest/ runtest.vim
3156  call assert_fails('normal ax', 'E565:')
3157  au! InsertCharPre
3158
3159  au InsertCharPre * vimgrepadd /RunTheTest/ runtest.vim
3160  call assert_fails('normal ax', 'E565:')
3161  au! InsertCharPre
3162
3163  au InsertCharPre * lvimgrep /RunTheTest/ runtest.vim
3164  call assert_fails('normal ax', 'E565:')
3165  au! InsertCharPre
3166
3167  au InsertCharPre * lvimgrepadd /RunTheTest/ runtest.vim
3168  call assert_fails('normal ax', 'E565:')
3169  au! InsertCharPre
3170
3171  bwipe!
3172endfunc
3173
3174" Tests for the quickfix buffer b:changedtick variable
3175func Xchangedtick_tests(cchar)
3176  call s:setup_commands(a:cchar)
3177
3178  new | only
3179
3180  Xexpr "" | Xexpr "" | Xexpr ""
3181
3182  Xopen
3183  Xolder
3184  Xolder
3185  Xaddexpr "F1:10:Line10"
3186  Xaddexpr "F2:20:Line20"
3187  call g:Xsetlist([{"filename":"F3", "lnum":30, "text":"Line30"}], 'a')
3188  call g:Xsetlist([], 'f')
3189  call assert_equal(8, getbufvar('%', 'changedtick'))
3190  Xclose
3191endfunc
3192
3193func Test_changedtick()
3194  call Xchangedtick_tests('c')
3195  call Xchangedtick_tests('l')
3196endfunc
3197
3198" Tests for parsing an expression using setqflist()
3199func Xsetexpr_tests(cchar)
3200  call s:setup_commands(a:cchar)
3201
3202  let t = ["File1:10:Line10", "File1:20:Line20"]
3203  call g:Xsetlist([], ' ', {'lines' : t})
3204  call g:Xsetlist([], 'a', {'lines' : ["File1:30:Line30"]})
3205
3206  let l = g:Xgetlist()
3207  call assert_equal(3, len(l))
3208  call assert_equal(20, l[1].lnum)
3209  call assert_equal('Line30', l[2].text)
3210  call g:Xsetlist([], 'r', {'lines' : ["File2:5:Line5"]})
3211  let l = g:Xgetlist()
3212  call assert_equal(1, len(l))
3213  call assert_equal('Line5', l[0].text)
3214  call assert_equal(-1, g:Xsetlist([], 'a', {'lines' : 10}))
3215  call assert_equal(-1, g:Xsetlist([], 'a', {'lines' : "F1:10:L10"}))
3216
3217  call g:Xsetlist([], 'f')
3218  " Add entries to multiple lists
3219  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["File1:10:Line10"]})
3220  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["File2:20:Line20"]})
3221  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["File1:15:Line15"]})
3222  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["File2:25:Line25"]})
3223  call assert_equal('Line15', g:Xgetlist({'nr':1, 'items':1}).items[1].text)
3224  call assert_equal('Line25', g:Xgetlist({'nr':2, 'items':1}).items[1].text)
3225
3226  " Adding entries using a custom efm
3227  set efm&
3228  call g:Xsetlist([], ' ', {'efm' : '%f#%l#%m',
3229				\ 'lines' : ["F1#10#L10", "F2#20#L20"]})
3230  call assert_equal(20, g:Xgetlist({'items':1}).items[1].lnum)
3231  call g:Xsetlist([], 'a', {'efm' : '%f#%l#%m', 'lines' : ["F3:30:L30"]})
3232  call assert_equal('F3:30:L30', g:Xgetlist({'items':1}).items[2].text)
3233  call assert_equal(20, g:Xgetlist({'items':1}).items[1].lnum)
3234  call assert_equal(-1, g:Xsetlist([], 'a', {'efm' : [],
3235				\ 'lines' : ['F1:10:L10']}))
3236endfunc
3237
3238func Test_setexpr()
3239  call Xsetexpr_tests('c')
3240  call Xsetexpr_tests('l')
3241endfunc
3242
3243" Tests for per quickfix/location list directory stack
3244func Xmultidirstack_tests(cchar)
3245  call s:setup_commands(a:cchar)
3246
3247  call g:Xsetlist([], 'f')
3248  Xexpr "" | Xexpr ""
3249
3250  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["Entering dir 'Xone/a'"]})
3251  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["Entering dir 'Xtwo/a'"]})
3252  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["one.txt:3:one one one"]})
3253  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["two.txt:5:two two two"]})
3254
3255  let l1 = g:Xgetlist({'nr':1, 'items':1})
3256  let l2 = g:Xgetlist({'nr':2, 'items':1})
3257  call assert_equal('Xone/a/one.txt', bufname(l1.items[1].bufnr))
3258  call assert_equal(3, l1.items[1].lnum)
3259  call assert_equal('Xtwo/a/two.txt', bufname(l2.items[1].bufnr))
3260  call assert_equal(5, l2.items[1].lnum)
3261endfunc
3262
3263func Test_multidirstack()
3264  call mkdir('Xone/a', 'p')
3265  call mkdir('Xtwo/a', 'p')
3266  let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7']
3267  call writefile(lines, 'Xone/a/one.txt')
3268  call writefile(lines, 'Xtwo/a/two.txt')
3269  let save_efm = &efm
3270  set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f'
3271
3272  call Xmultidirstack_tests('c')
3273  call Xmultidirstack_tests('l')
3274
3275  let &efm = save_efm
3276  call delete('Xone', 'rf')
3277  call delete('Xtwo', 'rf')
3278endfunc
3279
3280" Tests for per quickfix/location list file stack
3281func Xmultifilestack_tests(cchar)
3282  call s:setup_commands(a:cchar)
3283
3284  call g:Xsetlist([], 'f')
3285  Xexpr "" | Xexpr ""
3286
3287  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["[one.txt]"]})
3288  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["[two.txt]"]})
3289  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["(3,5) one one one"]})
3290  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["(5,9) two two two"]})
3291
3292  let l1 = g:Xgetlist({'nr':1, 'items':1})
3293  let l2 = g:Xgetlist({'nr':2, 'items':1})
3294  call assert_equal('one.txt', bufname(l1.items[1].bufnr))
3295  call assert_equal(3, l1.items[1].lnum)
3296  call assert_equal('two.txt', bufname(l2.items[1].bufnr))
3297  call assert_equal(5, l2.items[1].lnum)
3298
3299  " Test for start of a new error line in the same line where a previous
3300  " error line ends with a file stack.
3301  let efm_val = 'Error\ l%l\ in\ %f,'
3302  let efm_val .= '%-P%>(%f%r,Error\ l%l\ in\ %m,%-Q)%r'
3303  let l = g:Xgetlist({'lines' : [
3304	      \ '(one.txt',
3305	      \ 'Error l4 in one.txt',
3306	      \ ') (two.txt',
3307	      \ 'Error l6 in two.txt',
3308	      \ ')',
3309	      \ 'Error l8 in one.txt'
3310	      \ ], 'efm' : efm_val})
3311  call assert_equal(3, len(l.items))
3312  call assert_equal('one.txt', bufname(l.items[0].bufnr))
3313  call assert_equal(4, l.items[0].lnum)
3314  call assert_equal('one.txt', l.items[0].text)
3315  call assert_equal('two.txt', bufname(l.items[1].bufnr))
3316  call assert_equal(6, l.items[1].lnum)
3317  call assert_equal('two.txt', l.items[1].text)
3318  call assert_equal('one.txt', bufname(l.items[2].bufnr))
3319  call assert_equal(8, l.items[2].lnum)
3320  call assert_equal('', l.items[2].text)
3321endfunc
3322
3323func Test_multifilestack()
3324  let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7']
3325  call writefile(lines, 'one.txt')
3326  call writefile(lines, 'two.txt')
3327  let save_efm = &efm
3328  set efm=%+P[%f],(%l\\,%c)\ %m,%-Q
3329
3330  call Xmultifilestack_tests('c')
3331  call Xmultifilestack_tests('l')
3332
3333  let &efm = save_efm
3334  call delete('one.txt')
3335  call delete('two.txt')
3336endfunc
3337
3338" Tests for per buffer 'efm' setting
3339func Test_perbuf_efm()
3340  call writefile(["File1-10-Line10"], 'one.txt')
3341  call writefile(["File2#20#Line20"], 'two.txt')
3342  set efm=%f#%l#%m
3343  new | only
3344  new
3345  setlocal efm=%f-%l-%m
3346  cfile one.txt
3347  wincmd w
3348  caddfile two.txt
3349
3350  let l = getqflist()
3351  call assert_equal(10, l[0].lnum)
3352  call assert_equal('Line20', l[1].text)
3353
3354  set efm&
3355  new | only
3356  call delete('one.txt')
3357  call delete('two.txt')
3358endfunc
3359
3360" Open multiple help windows using ":lhelpgrep
3361" This test used to crash Vim
3362func Test_Multi_LL_Help()
3363  new | only
3364  lhelpgrep window
3365  lopen
3366  e#
3367  lhelpgrep buffer
3368  call assert_equal(3, winnr('$'))
3369  call assert_true(len(getloclist(1)) != 0)
3370  call assert_true(len(getloclist(2)) != 0)
3371  new | only
3372endfunc
3373
3374" Tests for adding new quickfix lists using setqflist()
3375func XaddQf_tests(cchar)
3376  call s:setup_commands(a:cchar)
3377
3378  " Create a new list using ' ' for action
3379  call g:Xsetlist([], 'f')
3380  call g:Xsetlist([], ' ', {'title' : 'Test1'})
3381  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3382  call assert_equal(1, l.nr)
3383  call assert_equal('Test1', l.title)
3384
3385  " Create a new list using ' ' for action and '$' for 'nr'
3386  call g:Xsetlist([], 'f')
3387  call g:Xsetlist([], ' ', {'title' : 'Test2', 'nr' : '$'})
3388  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3389  call assert_equal(1, l.nr)
3390  call assert_equal('Test2', l.title)
3391
3392  " Create a new list using 'a' for action
3393  call g:Xsetlist([], 'f')
3394  call g:Xsetlist([], 'a', {'title' : 'Test3'})
3395  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3396  call assert_equal(1, l.nr)
3397  call assert_equal('Test3', l.title)
3398
3399  " Create a new list using 'a' for action and '$' for 'nr'
3400  call g:Xsetlist([], 'f')
3401  call g:Xsetlist([], 'a', {'title' : 'Test3', 'nr' : '$'})
3402  call g:Xsetlist([], 'a', {'title' : 'Test4'})
3403  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3404  call assert_equal(1, l.nr)
3405  call assert_equal('Test4', l.title)
3406
3407  " Adding a quickfix list should remove all the lists following the current
3408  " list.
3409  Xexpr "" | Xexpr "" | Xexpr ""
3410  silent! 10Xolder
3411  call g:Xsetlist([], ' ', {'title' : 'Test5'})
3412  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3413  call assert_equal(2, l.nr)
3414  call assert_equal('Test5', l.title)
3415
3416  " Add a quickfix list using '$' as the list number.
3417  let lastqf = g:Xgetlist({'nr':'$'}).nr
3418  silent! 99Xolder
3419  call g:Xsetlist([], ' ', {'nr' : '$', 'title' : 'Test6'})
3420  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3421  call assert_equal(lastqf + 1, l.nr)
3422  call assert_equal('Test6', l.title)
3423
3424  " Add a quickfix list using 'nr' set to one more than the quickfix
3425  " list size.
3426  let lastqf = g:Xgetlist({'nr':'$'}).nr
3427  silent! 99Xolder
3428  call g:Xsetlist([], ' ', {'nr' : lastqf + 1, 'title' : 'Test7'})
3429  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3430  call assert_equal(lastqf + 1, l.nr)
3431  call assert_equal('Test7', l.title)
3432
3433  " Add a quickfix list to a stack with 10 lists using 'nr' set to '$'
3434  exe repeat('Xexpr "" |', 9) . 'Xexpr ""'
3435  silent! 99Xolder
3436  call g:Xsetlist([], ' ', {'nr' : '$', 'title' : 'Test8'})
3437  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3438  call assert_equal(10, l.nr)
3439  call assert_equal('Test8', l.title)
3440
3441  " Add a quickfix list using 'nr' set to a value greater than 10
3442  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : 12, 'title' : 'Test9'}))
3443
3444  " Try adding a quickfix list with 'nr' set to a value greater than the
3445  " quickfix list size but less than 10.
3446  call g:Xsetlist([], 'f')
3447  Xexpr "" | Xexpr "" | Xexpr ""
3448  silent! 99Xolder
3449  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : 8, 'title' : 'Test10'}))
3450
3451  " Add a quickfix list using 'nr' set to a some string or list
3452  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : [1,2], 'title' : 'Test11'}))
3453endfunc
3454
3455func Test_add_qf()
3456  call XaddQf_tests('c')
3457  call XaddQf_tests('l')
3458endfunc
3459
3460" Test for getting the quickfix list items from some text without modifying
3461" the quickfix stack
3462func XgetListFromLines(cchar)
3463  call s:setup_commands(a:cchar)
3464  call g:Xsetlist([], 'f')
3465
3466  let l = g:Xgetlist({'lines' : ["File2:20:Line20", "File2:30:Line30"]}).items
3467  call assert_equal(2, len(l))
3468  call assert_equal(30, l[1].lnum)
3469
3470  call assert_equal({}, g:Xgetlist({'lines' : 10}))
3471  call assert_equal({}, g:Xgetlist({'lines' : 'File1:10:Line10'}))
3472  call assert_equal([], g:Xgetlist({'lines' : []}).items)
3473  call assert_equal([], g:Xgetlist({'lines' : [10, 20]}).items)
3474
3475  " Parse text using a custom efm
3476  set efm&
3477  let l = g:Xgetlist({'lines':['File3#30#Line30'], 'efm' : '%f#%l#%m'}).items
3478  call assert_equal('Line30', l[0].text)
3479  let l = g:Xgetlist({'lines':['File3:30:Line30'], 'efm' : '%f-%l-%m'}).items
3480  call assert_equal('File3:30:Line30', l[0].text)
3481  let l = g:Xgetlist({'lines':['File3:30:Line30'], 'efm' : [1,2]})
3482  call assert_equal({}, l)
3483  call assert_fails("call g:Xgetlist({'lines':['abc'], 'efm':'%2'})", 'E376:')
3484  call assert_fails("call g:Xgetlist({'lines':['abc'], 'efm':''})", 'E378:')
3485
3486  " Make sure that the quickfix stack is not modified
3487  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
3488endfunc
3489
3490func Test_get_list_from_lines()
3491  call XgetListFromLines('c')
3492  call XgetListFromLines('l')
3493endfunc
3494
3495" Tests for the quickfix list id
3496func Xqfid_tests(cchar)
3497  call s:setup_commands(a:cchar)
3498
3499  call g:Xsetlist([], 'f')
3500  call assert_equal(0, g:Xgetlist({'id':0}).id)
3501  Xexpr ''
3502  let start_id = g:Xgetlist({'id' : 0}).id
3503  Xexpr '' | Xexpr ''
3504  Xolder
3505  call assert_equal(start_id, g:Xgetlist({'id':0, 'nr':1}).id)
3506  call assert_equal(start_id + 1, g:Xgetlist({'id':0, 'nr':0}).id)
3507  call assert_equal(start_id + 2, g:Xgetlist({'id':0, 'nr':'$'}).id)
3508  call assert_equal(0, g:Xgetlist({'id':0, 'nr':99}).id)
3509  call assert_equal(2, g:Xgetlist({'id':start_id + 1, 'nr':0}).nr)
3510  call assert_equal(0, g:Xgetlist({'id':99, 'nr':0}).id)
3511  call assert_equal(0, g:Xgetlist({'id':"abc", 'nr':0}).id)
3512
3513  call g:Xsetlist([], 'a', {'id':start_id, 'context':[1,2]})
3514  call assert_equal([1,2], g:Xgetlist({'nr':1, 'context':1}).context)
3515  call g:Xsetlist([], 'a', {'id':start_id+1, 'lines':['F1:10:L10']})
3516  call assert_equal('L10', g:Xgetlist({'nr':2, 'items':1}).items[0].text)
3517  call assert_equal(-1, g:Xsetlist([], 'a', {'id':999, 'title':'Vim'}))
3518  call assert_equal(-1, g:Xsetlist([], 'a', {'id':'abc', 'title':'Vim'}))
3519
3520  let qfid = g:Xgetlist({'id':0, 'nr':0})
3521  call g:Xsetlist([], 'f')
3522  call assert_equal(0, g:Xgetlist({'id':qfid, 'nr':0}).id)
3523endfunc
3524
3525func Test_qf_id()
3526  call Xqfid_tests('c')
3527  call Xqfid_tests('l')
3528endfunc
3529
3530func Xqfjump_tests(cchar)
3531  call s:setup_commands(a:cchar)
3532
3533  call writefile(["Line1\tFoo", "Line2"], 'F1')
3534  call writefile(["Line1\tBar", "Line2"], 'F2')
3535  call writefile(["Line1\tBaz", "Line2"], 'F3')
3536
3537  call g:Xsetlist([], 'f')
3538
3539  " Tests for
3540  "   Jumping to a line using a pattern
3541  "   Jumping to a column greater than the last column in a line
3542  "   Jumping to a line greater than the last line in the file
3543  let l = []
3544  for i in range(1, 7)
3545    call add(l, {})
3546  endfor
3547  let l[0].filename='F1'
3548  let l[0].pattern='Line1'
3549  let l[1].filename='F2'
3550  let l[1].pattern='Line1'
3551  let l[2].filename='F3'
3552  let l[2].pattern='Line1'
3553  let l[3].filename='F3'
3554  let l[3].lnum=1
3555  let l[3].col=9
3556  let l[3].vcol=1
3557  let l[4].filename='F3'
3558  let l[4].lnum=99
3559  let l[5].filename='F3'
3560  let l[5].lnum=1
3561  let l[5].col=99
3562  let l[5].vcol=1
3563  let l[6].filename='F3'
3564  let l[6].pattern='abcxyz'
3565
3566  call g:Xsetlist([], ' ', {'items' : l})
3567  Xopen | only
3568  2Xnext
3569  call assert_equal(3, g:Xgetlist({'idx' : 0}).idx)
3570  call assert_equal('F3', @%)
3571  Xnext
3572  call assert_equal(7, col('.'))
3573  Xnext
3574  call assert_equal(2, line('.'))
3575  Xnext
3576  call assert_equal(9, col('.'))
3577  2
3578  Xnext
3579  call assert_equal(2, line('.'))
3580
3581  if a:cchar == 'l'
3582    " When jumping to a location list entry in the location list window and
3583    " no usable windows are available, then a new window should be opened.
3584    enew! | new | only
3585    call g:Xsetlist([], 'f')
3586    setlocal buftype=nofile
3587    new
3588    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']})
3589    Xopen
3590    let winid = win_getid()
3591    wincmd p
3592    close
3593    call win_gotoid(winid)
3594    Xnext
3595    call assert_equal(3, winnr('$'))
3596    call assert_equal(1, winnr())
3597    call assert_equal(2, line('.'))
3598
3599    " When jumping to an entry in the location list window and the window
3600    " associated with the location list is not present and a window containing
3601    " the file is already present, then that window should be used.
3602    close
3603    belowright new
3604    call g:Xsetlist([], 'f')
3605    edit F3
3606    call win_gotoid(winid)
3607    Xlast
3608    call assert_equal(3, winnr())
3609    call assert_equal(6, g:Xgetlist({'size' : 1}).size)
3610    call assert_equal(winid, g:Xgetlist({'winid' : 1}).winid)
3611  endif
3612
3613  " Cleanup
3614  enew!
3615  new | only
3616
3617  call delete('F1')
3618  call delete('F2')
3619  call delete('F3')
3620endfunc
3621
3622func Test_qfjump()
3623  call Xqfjump_tests('c')
3624  call Xqfjump_tests('l')
3625endfunc
3626
3627" Tests for the getqflist() and getloclist() functions when the list is not
3628" present or is empty
3629func Xgetlist_empty_tests(cchar)
3630  call s:setup_commands(a:cchar)
3631
3632  " Empty quickfix stack
3633  call g:Xsetlist([], 'f')
3634  call assert_equal('', g:Xgetlist({'context' : 0}).context)
3635  call assert_equal(0, g:Xgetlist({'id' : 0}).id)
3636  call assert_equal(0, g:Xgetlist({'idx' : 0}).idx)
3637  call assert_equal([], g:Xgetlist({'items' : 0}).items)
3638  call assert_equal(0, g:Xgetlist({'nr' : 0}).nr)
3639  call assert_equal(0, g:Xgetlist({'size' : 0}).size)
3640  call assert_equal('', g:Xgetlist({'title' : 0}).title)
3641  call assert_equal(0, g:Xgetlist({'winid' : 0}).winid)
3642  call assert_equal(0, g:Xgetlist({'changedtick' : 0}).changedtick)
3643  if a:cchar == 'c'
3644    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0,
3645		  \ 'items' : [], 'nr' : 0, 'size' : 0, 'qfbufnr' : 0,
3646		  \ 'title' : '', 'winid' : 0, 'changedtick': 0,
3647                  \ 'quickfixtextfunc' : ''}, g:Xgetlist({'all' : 0}))
3648  else
3649    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0,
3650		\ 'items' : [], 'nr' : 0, 'size' : 0, 'title' : '',
3651		\ 'winid' : 0, 'changedtick': 0, 'filewinid' : 0,
3652		\ 'qfbufnr' : 0, 'quickfixtextfunc' : ''},
3653		\ g:Xgetlist({'all' : 0}))
3654  endif
3655
3656  " Quickfix window with empty stack
3657  silent! Xopen
3658  let qfwinid = (a:cchar == 'c') ? win_getid() : 0
3659  let qfbufnr = (a:cchar == 'c') ? bufnr('') : 0
3660  call assert_equal(qfwinid, g:Xgetlist({'winid' : 0}).winid)
3661  Xclose
3662
3663  " Empty quickfix list
3664  Xexpr ""
3665  call assert_equal('', g:Xgetlist({'context' : 0}).context)
3666  call assert_notequal(0, g:Xgetlist({'id' : 0}).id)
3667  call assert_equal(0, g:Xgetlist({'idx' : 0}).idx)
3668  call assert_equal([], g:Xgetlist({'items' : 0}).items)
3669  call assert_notequal(0, g:Xgetlist({'nr' : 0}).nr)
3670  call assert_equal(0, g:Xgetlist({'size' : 0}).size)
3671  call assert_notequal('', g:Xgetlist({'title' : 0}).title)
3672  call assert_equal(0, g:Xgetlist({'winid' : 0}).winid)
3673  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3674
3675  let qfid = g:Xgetlist({'id' : 0}).id
3676  call g:Xsetlist([], 'f')
3677
3678  " Non-existing quickfix identifier
3679  call assert_equal('', g:Xgetlist({'id' : qfid, 'context' : 0}).context)
3680  call assert_equal(0, g:Xgetlist({'id' : qfid}).id)
3681  call assert_equal(0, g:Xgetlist({'id' : qfid, 'idx' : 0}).idx)
3682  call assert_equal([], g:Xgetlist({'id' : qfid, 'items' : 0}).items)
3683  call assert_equal(0, g:Xgetlist({'id' : qfid, 'nr' : 0}).nr)
3684  call assert_equal(0, g:Xgetlist({'id' : qfid, 'size' : 0}).size)
3685  call assert_equal('', g:Xgetlist({'id' : qfid, 'title' : 0}).title)
3686  call assert_equal(0, g:Xgetlist({'id' : qfid, 'winid' : 0}).winid)
3687  call assert_equal(0, g:Xgetlist({'id' : qfid, 'changedtick' : 0}).changedtick)
3688  if a:cchar == 'c'
3689    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
3690		\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
3691		\ 'qfbufnr' : qfbufnr, 'quickfixtextfunc' : '',
3692		\ 'changedtick' : 0}, g:Xgetlist({'id' : qfid, 'all' : 0}))
3693  else
3694    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
3695		\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
3696		\ 'changedtick' : 0, 'filewinid' : 0, 'qfbufnr' : 0,
3697                \ 'quickfixtextfunc' : ''},
3698		\ g:Xgetlist({'id' : qfid, 'all' : 0}))
3699  endif
3700
3701  " Non-existing quickfix list number
3702  call assert_equal('', g:Xgetlist({'nr' : 5, 'context' : 0}).context)
3703  call assert_equal(0, g:Xgetlist({'nr' : 5}).nr)
3704  call assert_equal(0, g:Xgetlist({'nr' : 5, 'idx' : 0}).idx)
3705  call assert_equal([], g:Xgetlist({'nr' : 5, 'items' : 0}).items)
3706  call assert_equal(0, g:Xgetlist({'nr' : 5, 'id' : 0}).id)
3707  call assert_equal(0, g:Xgetlist({'nr' : 5, 'size' : 0}).size)
3708  call assert_equal('', g:Xgetlist({'nr' : 5, 'title' : 0}).title)
3709  call assert_equal(0, g:Xgetlist({'nr' : 5, 'winid' : 0}).winid)
3710  call assert_equal(0, g:Xgetlist({'nr' : 5, 'changedtick' : 0}).changedtick)
3711  if a:cchar == 'c'
3712    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
3713		\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
3714		\ 'changedtick' : 0, 'qfbufnr' : qfbufnr,
3715                \ 'quickfixtextfunc' : ''}, g:Xgetlist({'nr' : 5, 'all' : 0}))
3716  else
3717    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
3718		\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
3719		\ 'changedtick' : 0, 'filewinid' : 0, 'qfbufnr' : 0,
3720                \ 'quickfixtextfunc' : ''}, g:Xgetlist({'nr' : 5, 'all' : 0}))
3721  endif
3722endfunc
3723
3724func Test_getqflist()
3725  call Xgetlist_empty_tests('c')
3726  call Xgetlist_empty_tests('l')
3727endfunc
3728
3729func Test_getqflist_invalid_nr()
3730  " The following commands used to crash Vim
3731  cexpr ""
3732  call getqflist({'nr' : $XXX_DOES_NOT_EXIST_XXX})
3733
3734  " Cleanup
3735  call setqflist([], 'r')
3736endfunc
3737
3738" Tests for the quickfix/location list changedtick
3739func Xqftick_tests(cchar)
3740  call s:setup_commands(a:cchar)
3741
3742  call g:Xsetlist([], 'f')
3743
3744  Xexpr "F1:10:Line10"
3745  let qfid = g:Xgetlist({'id' : 0}).id
3746  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3747  Xaddexpr "F2:20:Line20\nF2:21:Line21"
3748  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
3749  call g:Xsetlist([], 'a', {'lines' : ["F3:30:Line30", "F3:31:Line31"]})
3750  call assert_equal(3, g:Xgetlist({'changedtick' : 0}).changedtick)
3751  call g:Xsetlist([], 'r', {'lines' : ["F4:40:Line40"]})
3752  call assert_equal(4, g:Xgetlist({'changedtick' : 0}).changedtick)
3753  call g:Xsetlist([], 'a', {'title' : 'New Title'})
3754  call assert_equal(5, g:Xgetlist({'changedtick' : 0}).changedtick)
3755
3756  enew!
3757  call append(0, ["F5:50:L50", "F6:60:L60"])
3758  Xaddbuffer
3759  call assert_equal(6, g:Xgetlist({'changedtick' : 0}).changedtick)
3760  enew!
3761
3762  call g:Xsetlist([], 'a', {'context' : {'bus' : 'pci'}})
3763  call assert_equal(7, g:Xgetlist({'changedtick' : 0}).changedtick)
3764  call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'},
3765	      \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], 'a')
3766  call assert_equal(8, g:Xgetlist({'changedtick' : 0}).changedtick)
3767  call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'},
3768	      \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], ' ')
3769  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3770  call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'},
3771	      \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], 'r')
3772  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
3773
3774  call writefile(["F8:80:L80", "F8:81:L81"], "Xone")
3775  Xfile Xone
3776  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3777  Xaddfile Xone
3778  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
3779
3780  " Test case for updating a non-current quickfix list
3781  call g:Xsetlist([], 'f')
3782  Xexpr "F1:1:L1"
3783  Xexpr "F2:2:L2"
3784  call g:Xsetlist([], 'a', {'nr' : 1, "lines" : ["F10:10:L10"]})
3785  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3786  call assert_equal(2, g:Xgetlist({'nr' : 1, 'changedtick' : 0}).changedtick)
3787
3788  call delete("Xone")
3789endfunc
3790
3791func Test_qf_tick()
3792  call Xqftick_tests('c')
3793  call Xqftick_tests('l')
3794endfunc
3795
3796" Test helpgrep with lang specifier
3797func Xtest_helpgrep_with_lang_specifier(cchar)
3798  call s:setup_commands(a:cchar)
3799  Xhelpgrep Vim@en
3800  call assert_equal('help', &filetype)
3801  call assert_notequal(0, g:Xgetlist({'nr' : '$'}).nr)
3802  new | only
3803endfunc
3804
3805func Test_helpgrep_with_lang_specifier()
3806  call Xtest_helpgrep_with_lang_specifier('c')
3807  call Xtest_helpgrep_with_lang_specifier('l')
3808endfunc
3809
3810" The following test used to crash Vim.
3811" Open the location list window and close the regular window associated with
3812" the location list. When the garbage collection runs now, it incorrectly
3813" marks the location list context as not in use and frees the context.
3814func Test_ll_window_ctx()
3815  call setloclist(0, [], 'f')
3816  call setloclist(0, [], 'a', {'context' : []})
3817  lopen | only
3818  call test_garbagecollect_now()
3819  echo getloclist(0, {'context' : 1}).context
3820  enew | only
3821endfunc
3822
3823" The following test used to crash vim
3824func Test_lfile_crash()
3825  sp Xtest
3826  au QuickFixCmdPre * bw
3827  call assert_fails('lfile', 'E40:')
3828  au! QuickFixCmdPre
3829endfunc
3830
3831" The following test used to crash vim
3832func Test_lbuffer_crash()
3833  sv Xtest
3834  augroup QF_Test
3835    au!
3836    au * * bw
3837  augroup END
3838  lbuffer
3839  augroup QF_Test
3840    au!
3841  augroup END
3842endfunc
3843
3844" The following test used to crash vim
3845func Test_lexpr_crash()
3846  augroup QF_Test
3847    au!
3848    au * * call setloclist(0, [], 'f')
3849  augroup END
3850  lexpr ""
3851  augroup QF_Test
3852    au!
3853  augroup END
3854
3855  enew | only
3856  augroup QF_Test
3857    au!
3858    au BufNew * call setloclist(0, [], 'f')
3859  augroup END
3860  lexpr 'x:1:x'
3861  augroup QF_Test
3862    au!
3863  augroup END
3864
3865  enew | only
3866  lexpr ''
3867  lopen
3868  augroup QF_Test
3869    au!
3870    au FileType * call setloclist(0, [], 'f')
3871  augroup END
3872  lexpr ''
3873  augroup QF_Test
3874    au!
3875  augroup END
3876endfunc
3877
3878" The following test used to crash Vim
3879func Test_lvimgrep_crash()
3880  sv Xtest
3881  augroup QF_Test
3882    au!
3883    au * * call setloclist(0, [], 'f')
3884  augroup END
3885  lvimgrep quickfix test_quickfix.vim
3886  augroup QF_Test
3887    au!
3888  augroup END
3889
3890  new | only
3891  augroup QF_Test
3892    au!
3893    au BufEnter * call setloclist(0, [], 'r')
3894  augroup END
3895  call assert_fails('lvimgrep Test_lvimgrep_crash *', 'E926:')
3896  augroup QF_Test
3897    au!
3898  augroup END
3899
3900  enew | only
3901endfunc
3902
3903func Test_lvimgrep_crash2()
3904  au BufNewFile x sfind
3905  call assert_fails('lvimgrep x x', 'E471:')
3906  call assert_fails('lvimgrep x x x', 'E471:')
3907
3908  au! BufNewFile
3909endfunc
3910
3911" Test for the position of the quickfix and location list window
3912func Test_qfwin_pos()
3913  " Open two windows
3914  new | only
3915  new
3916  cexpr ['F1:10:L10']
3917  copen
3918  " Quickfix window should be the bottom most window
3919  call assert_equal(3, winnr())
3920  close
3921  " Open at the very top
3922  wincmd t
3923  topleft copen
3924  call assert_equal(1, winnr())
3925  close
3926  " open left of the current window
3927  wincmd t
3928  below new
3929  leftabove copen
3930  call assert_equal(2, winnr())
3931  close
3932  " open right of the current window
3933  rightbelow copen
3934  call assert_equal(3, winnr())
3935  close
3936endfunc
3937
3938" Tests for quickfix/location lists changed by autocommands when
3939" :vimgrep/:lvimgrep commands are running.
3940func Test_vimgrep_autocmd()
3941  call setqflist([], 'f')
3942  call writefile(['stars'], 'Xtest1.txt')
3943  call writefile(['stars'], 'Xtest2.txt')
3944
3945  " Test 1:
3946  " When searching for a pattern using :vimgrep, if the quickfix list is
3947  " changed by an autocmd, the results should be added to the correct quickfix
3948  " list.
3949  autocmd BufRead Xtest2.txt cexpr '' | cexpr ''
3950  silent vimgrep stars Xtest*.txt
3951  call assert_equal(1, getqflist({'nr' : 0}).nr)
3952  call assert_equal(3, getqflist({'nr' : '$'}).nr)
3953  call assert_equal('Xtest2.txt', bufname(getqflist()[1].bufnr))
3954  au! BufRead Xtest2.txt
3955
3956  " Test 2:
3957  " When searching for a pattern using :vimgrep, if the quickfix list is
3958  " freed, then a error should be given.
3959  silent! %bwipe!
3960  call setqflist([], 'f')
3961  autocmd BufRead Xtest2.txt for i in range(10) | cexpr '' | endfor
3962  call assert_fails('vimgrep stars Xtest*.txt', 'E925:')
3963  au! BufRead Xtest2.txt
3964
3965  " Test 3:
3966  " When searching for a pattern using :lvimgrep, if the location list is
3967  " freed, then the command should error out.
3968  silent! %bwipe!
3969  let g:save_winid = win_getid()
3970  autocmd BufRead Xtest2.txt call setloclist(g:save_winid, [], 'f')
3971  call assert_fails('lvimgrep stars Xtest*.txt', 'E926:')
3972  au! BufRead Xtest2.txt
3973
3974  call delete('Xtest1.txt')
3975  call delete('Xtest2.txt')
3976  call setqflist([], 'f')
3977endfunc
3978
3979" Test for an autocmd changing the current directory when running vimgrep
3980func Xvimgrep_autocmd_cd(cchar)
3981  call s:setup_commands(a:cchar)
3982
3983  %bwipe
3984  let save_cwd = getcwd()
3985
3986  augroup QF_Test
3987    au!
3988    autocmd BufRead * silent cd %:p:h
3989  augroup END
3990
3991  10Xvimgrep /vim/ Xdir/**
3992  let l = g:Xgetlist()
3993  call assert_equal('f1.txt', bufname(l[0].bufnr))
3994  call assert_equal('f2.txt', fnamemodify(bufname(l[2].bufnr), ':t'))
3995
3996  augroup QF_Test
3997    au!
3998  augroup END
3999
4000  exe 'cd ' . save_cwd
4001endfunc
4002
4003func Test_vimgrep_autocmd_cd()
4004  call mkdir('Xdir/a', 'p')
4005  call mkdir('Xdir/b', 'p')
4006  call writefile(['a_L1_vim', 'a_L2_vim'], 'Xdir/a/f1.txt')
4007  call writefile(['b_L1_vim', 'b_L2_vim'], 'Xdir/b/f2.txt')
4008  call Xvimgrep_autocmd_cd('c')
4009  call Xvimgrep_autocmd_cd('l')
4010  %bwipe
4011  call delete('Xdir', 'rf')
4012endfunc
4013
4014" The following test used to crash Vim
4015func Test_lhelpgrep_autocmd()
4016  lhelpgrep quickfix
4017  autocmd QuickFixCmdPost * call setloclist(0, [], 'f')
4018  lhelpgrep buffer
4019  call assert_equal('help', &filetype)
4020  call assert_equal(0, getloclist(0, {'nr' : '$'}).nr)
4021  lhelpgrep tabpage
4022  call assert_equal('help', &filetype)
4023  call assert_equal(1, getloclist(0, {'nr' : '$'}).nr)
4024  au! QuickFixCmdPost
4025
4026  new | only
4027  augroup QF_Test
4028    au!
4029    au BufEnter * call setqflist([], 'f')
4030  augroup END
4031  call assert_fails('helpgrep quickfix', 'E925:')
4032  " run the test with a help window already open
4033  help
4034  wincmd w
4035  call assert_fails('helpgrep quickfix', 'E925:')
4036  augroup QF_Test
4037    au! BufEnter
4038  augroup END
4039
4040  new | only
4041  augroup QF_Test
4042    au!
4043    au BufEnter * call setqflist([], 'r')
4044  augroup END
4045  call assert_fails('helpgrep quickfix', 'E925:')
4046  augroup QF_Test
4047    au! BufEnter
4048  augroup END
4049
4050  new | only
4051  augroup QF_Test
4052    au!
4053    au BufEnter * call setloclist(0, [], 'r')
4054  augroup END
4055  call assert_fails('lhelpgrep quickfix', 'E926:')
4056  augroup QF_Test
4057    au! BufEnter
4058  augroup END
4059
4060  new | only
4061endfunc
4062
4063" Test for shortening/simplifying the file name when opening the
4064" quickfix window or when displaying the quickfix list
4065func Test_shorten_fname()
4066  CheckUnix
4067  %bwipe
4068  " Create a quickfix list with a absolute path filename
4069  let fname = getcwd() . '/test_quickfix.vim'
4070  call setqflist([], ' ', {'lines':[fname . ":20:Line20"], 'efm':'%f:%l:%m'})
4071  call assert_equal(fname, bufname('test_quickfix.vim'))
4072  " Opening the quickfix window should simplify the file path
4073  cwindow
4074  call assert_equal('test_quickfix.vim', bufname('test_quickfix.vim'))
4075  cclose
4076  %bwipe
4077  " Create a quickfix list with a absolute path filename
4078  call setqflist([], ' ', {'lines':[fname . ":20:Line20"], 'efm':'%f:%l:%m'})
4079  call assert_equal(fname, bufname('test_quickfix.vim'))
4080  " Displaying the quickfix list should simplify the file path
4081  silent! clist
4082  call assert_equal('test_quickfix.vim', bufname('test_quickfix.vim'))
4083  " Add a few entries for the same file with different paths and check whether
4084  " the buffer name is shortened
4085  %bwipe
4086  call setqflist([], 'f')
4087  call setqflist([{'filename' : 'test_quickfix.vim', 'lnum' : 10},
4088        \ {'filename' : '../testdir/test_quickfix.vim', 'lnum' : 20},
4089        \ {'filename' : fname, 'lnum' : 30}], ' ')
4090  copen
4091  call assert_equal(['test_quickfix.vim|10| ',
4092        \ 'test_quickfix.vim|20| ',
4093        \ 'test_quickfix.vim|30| '], getline(1, '$'))
4094  cclose
4095endfunc
4096
4097" Quickfix title tests
4098" In the below tests, 'exe "cmd"' is used to invoke the quickfix commands.
4099" Otherwise due to indentation, the title is set with spaces at the beginning
4100" of the command.
4101func Test_qftitle()
4102  call writefile(["F1:1:Line1"], 'Xerr')
4103
4104  " :cexpr
4105  exe "cexpr readfile('Xerr')"
4106  call assert_equal(":cexpr readfile('Xerr')", getqflist({'title' : 1}).title)
4107
4108  " :cgetexpr
4109  exe "cgetexpr readfile('Xerr')"
4110  call assert_equal(":cgetexpr readfile('Xerr')",
4111					\ getqflist({'title' : 1}).title)
4112
4113  " :caddexpr
4114  call setqflist([], 'f')
4115  exe "caddexpr readfile('Xerr')"
4116  call assert_equal(":caddexpr readfile('Xerr')",
4117					\ getqflist({'title' : 1}).title)
4118
4119  " :cbuffer
4120  new Xerr
4121  exe "cbuffer"
4122  call assert_equal(':cbuffer (Xerr)', getqflist({'title' : 1}).title)
4123
4124  " :cgetbuffer
4125  edit Xerr
4126  exe "cgetbuffer"
4127  call assert_equal(':cgetbuffer (Xerr)', getqflist({'title' : 1}).title)
4128
4129  " :caddbuffer
4130  call setqflist([], 'f')
4131  edit Xerr
4132  exe "caddbuffer"
4133  call assert_equal(':caddbuffer (Xerr)', getqflist({'title' : 1}).title)
4134
4135  " :cfile
4136  exe "cfile Xerr"
4137  call assert_equal(':cfile Xerr', getqflist({'title' : 1}).title)
4138
4139  " :cgetfile
4140  exe "cgetfile Xerr"
4141  call assert_equal(':cgetfile Xerr', getqflist({'title' : 1}).title)
4142
4143  " :caddfile
4144  call setqflist([], 'f')
4145  exe "caddfile Xerr"
4146  call assert_equal(':caddfile Xerr', getqflist({'title' : 1}).title)
4147
4148  " :grep
4149  set grepprg=internal
4150  exe "grep F1 Xerr"
4151  call assert_equal(':grep F1 Xerr', getqflist({'title' : 1}).title)
4152
4153  " :grepadd
4154  call setqflist([], 'f')
4155  exe "grepadd F1 Xerr"
4156  call assert_equal(':grepadd F1 Xerr', getqflist({'title' : 1}).title)
4157  set grepprg&vim
4158
4159  " :vimgrep
4160  exe "vimgrep F1 Xerr"
4161  call assert_equal(':vimgrep F1 Xerr', getqflist({'title' : 1}).title)
4162
4163  " :vimgrepadd
4164  call setqflist([], 'f')
4165  exe "vimgrepadd F1 Xerr"
4166  call assert_equal(':vimgrepadd F1 Xerr', getqflist({'title' : 1}).title)
4167
4168  call setqflist(['F1:10:L10'], ' ')
4169  call assert_equal(':setqflist()', getqflist({'title' : 1}).title)
4170
4171  call setqflist([], 'f')
4172  call setqflist(['F1:10:L10'], 'a')
4173  call assert_equal(':setqflist()', getqflist({'title' : 1}).title)
4174
4175  call setqflist([], 'f')
4176  call setqflist(['F1:10:L10'], 'r')
4177  call assert_equal(':setqflist()', getqflist({'title' : 1}).title)
4178
4179  close
4180  call delete('Xerr')
4181
4182  call setqflist([], ' ', {'title' : 'Errors'})
4183  copen
4184  call assert_equal('Errors', w:quickfix_title)
4185  call setqflist([], 'r', {'items' : [{'filename' : 'a.c', 'lnum' : 10}]})
4186  call assert_equal('Errors', w:quickfix_title)
4187  cclose
4188
4189  " Switching to another quickfix list in one tab page should update the
4190  " quickfix window title and statusline in all the other tab pages also
4191  call setqflist([], 'f')
4192  %bw!
4193  cgetexpr ['file_one:1:1: error in the first quickfix list']
4194  call setqflist([], 'a', {'title': 'first quickfix list'})
4195  cgetexpr ['file_two:2:1: error in the second quickfix list']
4196  call setqflist([], 'a', {'title': 'second quickfix list'})
4197  copen
4198  wincmd t
4199  tabnew two
4200  copen
4201  wincmd t
4202  colder
4203  call assert_equal('first quickfix list', gettabwinvar(1, 2, 'quickfix_title'))
4204  call assert_equal('first quickfix list', gettabwinvar(2, 2, 'quickfix_title'))
4205  call assert_equal(1, tabpagewinnr(1))
4206  call assert_equal(1, tabpagewinnr(2))
4207  tabnew
4208  call setqflist([], 'a', {'title': 'new quickfix title'})
4209  call assert_equal('new quickfix title', gettabwinvar(1, 2, 'quickfix_title'))
4210  call assert_equal('new quickfix title', gettabwinvar(2, 2, 'quickfix_title'))
4211  %bw!
4212endfunc
4213
4214func Test_lbuffer_with_bwipe()
4215  new
4216  new
4217  augroup nasty
4218    au * * bwipe
4219  augroup END
4220  lbuffer
4221  augroup nasty
4222    au!
4223  augroup END
4224endfunc
4225
4226" Test for an autocmd freeing the quickfix/location list when cexpr/lexpr is
4227" running
4228func Xexpr_acmd_freelist(cchar)
4229  call s:setup_commands(a:cchar)
4230
4231  " This was using freed memory.
4232  augroup nasty
4233    au * * call g:Xsetlist([], 'f')
4234  augroup END
4235  Xexpr "x"
4236  augroup nasty
4237    au!
4238  augroup END
4239endfunc
4240
4241func Test_cexpr_acmd_freelist()
4242  call Xexpr_acmd_freelist('c')
4243  call Xexpr_acmd_freelist('l')
4244endfunc
4245
4246" Test for commands that create a new quickfix/location list and jump to the
4247" first error automatically.
4248func Xjumpto_first_error_test(cchar)
4249  call s:setup_commands(a:cchar)
4250
4251  call s:create_test_file('Xtestfile1')
4252  call s:create_test_file('Xtestfile2')
4253  let l = ['Xtestfile1:2:Line2', 'Xtestfile2:4:Line4']
4254
4255  " Test for cexpr/lexpr
4256  enew
4257  Xexpr l
4258  call assert_equal('Xtestfile1', @%)
4259  call assert_equal(2, line('.'))
4260
4261  " Test for cfile/lfile
4262  enew
4263  call writefile(l, 'Xerr')
4264  Xfile Xerr
4265  call assert_equal('Xtestfile1', @%)
4266  call assert_equal(2, line('.'))
4267
4268  " Test for cbuffer/lbuffer
4269  edit Xerr
4270  Xbuffer
4271  call assert_equal('Xtestfile1', @%)
4272  call assert_equal(2, line('.'))
4273
4274  call delete('Xerr')
4275  call delete('Xtestfile1')
4276  call delete('Xtestfile2')
4277endfunc
4278
4279func Test_jumpto_first_error()
4280  call Xjumpto_first_error_test('c')
4281  call Xjumpto_first_error_test('l')
4282endfunc
4283
4284" Test for a quickfix autocmd changing the quickfix/location list before
4285" jumping to the first error in the new list.
4286func Xautocmd_changelist(cchar)
4287  call s:setup_commands(a:cchar)
4288
4289  " Test for cfile/lfile
4290  call s:create_test_file('Xtestfile1')
4291  call s:create_test_file('Xtestfile2')
4292  Xexpr 'Xtestfile1:2:Line2'
4293  autocmd QuickFixCmdPost * Xolder
4294  call writefile(['Xtestfile2:4:Line4'], 'Xerr')
4295  Xfile Xerr
4296  call assert_equal('Xtestfile2', @%)
4297  call assert_equal(4, line('.'))
4298  autocmd! QuickFixCmdPost
4299
4300  " Test for cbuffer/lbuffer
4301  call g:Xsetlist([], 'f')
4302  Xexpr 'Xtestfile1:2:Line2'
4303  autocmd QuickFixCmdPost * Xolder
4304  call writefile(['Xtestfile2:4:Line4'], 'Xerr')
4305  edit Xerr
4306  Xbuffer
4307  call assert_equal('Xtestfile2', @%)
4308  call assert_equal(4, line('.'))
4309  autocmd! QuickFixCmdPost
4310
4311  " Test for cexpr/lexpr
4312  call g:Xsetlist([], 'f')
4313  Xexpr 'Xtestfile1:2:Line2'
4314  autocmd QuickFixCmdPost * Xolder
4315  Xexpr 'Xtestfile2:4:Line4'
4316  call assert_equal('Xtestfile2', @%)
4317  call assert_equal(4, line('.'))
4318  autocmd! QuickFixCmdPost
4319
4320  " The grepprg may not be set on non-Unix systems
4321  if has('unix')
4322    " Test for grep/lgrep
4323    call g:Xsetlist([], 'f')
4324    Xexpr 'Xtestfile1:2:Line2'
4325    autocmd QuickFixCmdPost * Xolder
4326    silent Xgrep Line5 Xtestfile2
4327    call assert_equal('Xtestfile2', @%)
4328    call assert_equal(5, line('.'))
4329    autocmd! QuickFixCmdPost
4330  endif
4331
4332  " Test for vimgrep/lvimgrep
4333  call g:Xsetlist([], 'f')
4334  Xexpr 'Xtestfile1:2:Line2'
4335  autocmd QuickFixCmdPost * Xolder
4336  silent Xvimgrep Line5 Xtestfile2
4337  call assert_equal('Xtestfile2', @%)
4338  call assert_equal(5, line('.'))
4339  autocmd! QuickFixCmdPost
4340
4341  " Test for autocommands clearing the quickfix list before jumping to the
4342  " first error. This should not result in an error
4343  autocmd QuickFixCmdPost * call g:Xsetlist([], 'r')
4344  let v:errmsg = ''
4345  " Test for cfile/lfile
4346  Xfile Xerr
4347  call assert_true(v:errmsg !~# 'E42:')
4348  " Test for cbuffer/lbuffer
4349  edit Xerr
4350  Xbuffer
4351  call assert_true(v:errmsg !~# 'E42:')
4352  " Test for cexpr/lexpr
4353  Xexpr 'Xtestfile2:4:Line4'
4354  call assert_true(v:errmsg !~# 'E42:')
4355  " Test for grep/lgrep
4356  " The grepprg may not be set on non-Unix systems
4357  if has('unix')
4358    silent Xgrep Line5 Xtestfile2
4359    call assert_true(v:errmsg !~# 'E42:')
4360  endif
4361  " Test for vimgrep/lvimgrep
4362  call assert_fails('silent Xvimgrep Line5 Xtestfile2', 'E480:')
4363  autocmd! QuickFixCmdPost
4364
4365  call delete('Xerr')
4366  call delete('Xtestfile1')
4367  call delete('Xtestfile2')
4368endfunc
4369
4370func Test_autocmd_changelist()
4371  call Xautocmd_changelist('c')
4372  call Xautocmd_changelist('l')
4373endfunc
4374
4375" Tests for the ':filter /pat/ clist' command
4376func Test_filter_clist()
4377  cexpr ['Xfile1:10:10:Line 10', 'Xfile2:15:15:Line 15']
4378  call assert_equal([' 2 Xfile2:15 col 15: Line 15'],
4379			\ split(execute('filter /Line 15/ clist'), "\n"))
4380  call assert_equal([' 1 Xfile1:10 col 10: Line 10'],
4381			\ split(execute('filter /Xfile1/ clist'), "\n"))
4382  call assert_equal([], split(execute('filter /abc/ clist'), "\n"))
4383
4384  call setqflist([{'module' : 'abc', 'pattern' : 'pat1'},
4385			\ {'module' : 'pqr', 'pattern' : 'pat2'}], ' ')
4386  call assert_equal([' 2 pqr:pat2:  '],
4387			\ split(execute('filter /pqr/ clist'), "\n"))
4388  call assert_equal([' 1 abc:pat1:  '],
4389			\ split(execute('filter /pat1/ clist'), "\n"))
4390endfunc
4391
4392" Tests for the "CTRL-W <CR>" command.
4393func Xview_result_split_tests(cchar)
4394  call s:setup_commands(a:cchar)
4395
4396  " Test that "CTRL-W <CR>" in a qf/ll window fails with empty list.
4397  call g:Xsetlist([])
4398  Xopen
4399  let l:win_count = winnr('$')
4400  call assert_fails('execute "normal! \<C-W>\<CR>"', 'E42:')
4401  call assert_equal(l:win_count, winnr('$'))
4402  Xclose
4403endfunc
4404
4405func Test_view_result_split()
4406  call Xview_result_split_tests('c')
4407  call Xview_result_split_tests('l')
4408endfunc
4409
4410" Test that :cc sets curswant
4411func Test_curswant()
4412  helpgrep quickfix
4413  normal! llll
4414  1cc
4415  call assert_equal(getcurpos()[4], virtcol('.'))
4416  cclose | helpclose
4417endfunc
4418
4419" Test for opening a file from the quickfix window using CTRL-W <Enter>
4420" doesn't leave an empty buffer around.
4421func Test_splitview()
4422  call s:create_test_file('Xtestfile1')
4423  call s:create_test_file('Xtestfile2')
4424  new | only
4425  let last_bufnr = bufnr('Test_sv_1', 1)
4426  let l = ['Xtestfile1:2:Line2', 'Xtestfile2:4:Line4']
4427  cgetexpr l
4428  copen
4429  let numbufs = len(getbufinfo())
4430  exe "normal \<C-W>\<CR>"
4431  copen
4432  exe "normal j\<C-W>\<CR>"
4433  " Make sure new empty buffers are not created
4434  call assert_equal(numbufs, len(getbufinfo()))
4435  " Creating a new buffer should use the next available buffer number
4436  call assert_equal(last_bufnr + 4, bufnr("Test_sv_2", 1))
4437  bwipe Test_sv_1
4438  bwipe Test_sv_2
4439  new | only
4440
4441  " When split opening files from location list window, make sure that two
4442  " windows doesn't refer to the same location list
4443  lgetexpr l
4444  let locid = getloclist(0, {'id' : 0}).id
4445  lopen
4446  exe "normal \<C-W>\<CR>"
4447  call assert_notequal(locid, getloclist(0, {'id' : 0}).id)
4448  call assert_equal(0, getloclist(0, {'winid' : 0}).winid)
4449  new | only
4450
4451  " When split opening files from a helpgrep location list window, a new help
4452  " window should be opened with a copy of the location list.
4453  lhelpgrep window
4454  let locid = getloclist(0, {'id' : 0}).id
4455  lwindow
4456  exe "normal j\<C-W>\<CR>"
4457  call assert_notequal(locid, getloclist(0, {'id' : 0}).id)
4458  call assert_equal(0, getloclist(0, {'winid' : 0}).winid)
4459  new | only
4460
4461  " Using :split or :vsplit from a quickfix window should behave like a :new
4462  " or a :vnew command
4463  copen
4464  split
4465  call assert_equal(3, winnr('$'))
4466  let l = getwininfo()
4467  call assert_equal([0, 0, 1], [l[0].quickfix, l[1].quickfix, l[2].quickfix])
4468  close
4469  copen
4470  vsplit
4471  let l = getwininfo()
4472  call assert_equal([0, 0, 1], [l[0].quickfix, l[1].quickfix, l[2].quickfix])
4473  new | only
4474
4475  call delete('Xtestfile1')
4476  call delete('Xtestfile2')
4477endfunc
4478
4479" Test for parsing entries using visual screen column
4480func Test_viscol()
4481  enew
4482  call writefile(["Col1\tCol2\tCol3"], 'Xfile1')
4483  edit Xfile1
4484
4485  " Use byte offset for column number
4486  set efm&
4487  cexpr "Xfile1:1:5:XX\nXfile1:1:9:YY\nXfile1:1:20:ZZ"
4488  call assert_equal([5, 8], [col('.'), virtcol('.')])
4489  cnext
4490  call assert_equal([9, 12], [col('.'), virtcol('.')])
4491  cnext
4492  call assert_equal([14, 20], [col('.'), virtcol('.')])
4493
4494  " Use screen column offset for column number
4495  set efm=%f:%l:%v:%m
4496  cexpr "Xfile1:1:8:XX\nXfile1:1:12:YY\nXfile1:1:20:ZZ"
4497  call assert_equal([5, 8], [col('.'), virtcol('.')])
4498  cnext
4499  call assert_equal([9, 12], [col('.'), virtcol('.')])
4500  cnext
4501  call assert_equal([14, 20], [col('.'), virtcol('.')])
4502  cexpr "Xfile1:1:6:XX\nXfile1:1:15:YY\nXfile1:1:24:ZZ"
4503  call assert_equal([5, 8], [col('.'), virtcol('.')])
4504  cnext
4505  call assert_equal([10, 16], [col('.'), virtcol('.')])
4506  cnext
4507  call assert_equal([14, 20], [col('.'), virtcol('.')])
4508
4509  enew
4510  call writefile(["Col1\täü\töß\tCol4"], 'Xfile1')
4511
4512  " Use byte offset for column number
4513  set efm&
4514  cexpr "Xfile1:1:8:XX\nXfile1:1:11:YY\nXfile1:1:16:ZZ"
4515  call assert_equal([8, 10], [col('.'), virtcol('.')])
4516  cnext
4517  call assert_equal([11, 17], [col('.'), virtcol('.')])
4518  cnext
4519  call assert_equal([16, 25], [col('.'), virtcol('.')])
4520
4521  " Use screen column offset for column number
4522  set efm=%f:%l:%v:%m
4523  cexpr "Xfile1:1:10:XX\nXfile1:1:17:YY\nXfile1:1:25:ZZ"
4524  call assert_equal([8, 10], [col('.'), virtcol('.')])
4525  cnext
4526  call assert_equal([11, 17], [col('.'), virtcol('.')])
4527  cnext
4528  call assert_equal([16, 25], [col('.'), virtcol('.')])
4529
4530  " Use screen column number with a multi-line error message
4531  enew
4532  call writefile(["à test"], 'Xfile1')
4533  set efm=%E===\ %f\ ===,%C%l:%v,%Z%m
4534  cexpr ["=== Xfile1 ===", "1:3", "errormsg"]
4535  call assert_equal('Xfile1', @%)
4536  call assert_equal([0, 1, 4, 0], getpos('.'))
4537
4538  " Repeat previous test with byte offset %c: ensure that fix to issue #7145
4539  " does not break this
4540  set efm=%E===\ %f\ ===,%C%l:%c,%Z%m
4541  cexpr ["=== Xfile1 ===", "1:3", "errormsg"]
4542  call assert_equal('Xfile1', @%)
4543  call assert_equal([0, 1, 3, 0], getpos('.'))
4544
4545  enew | only
4546  set efm&
4547  call delete('Xfile1')
4548endfunc
4549
4550" Test for the quickfix window buffer
4551func Xqfbuf_test(cchar)
4552  call s:setup_commands(a:cchar)
4553
4554  " Quickfix buffer should be reused across closing and opening a quickfix
4555  " window
4556  Xexpr "F1:10:Line10"
4557  Xopen
4558  let qfbnum = bufnr('')
4559  Xclose
4560  " Even after the quickfix window is closed, the buffer should be loaded
4561  call assert_true(bufloaded(qfbnum))
4562  call assert_true(qfbnum, g:Xgetlist({'qfbufnr' : 0}).qfbufnr)
4563  Xopen
4564  " Buffer should be reused when opening the window again
4565  call assert_equal(qfbnum, bufnr(''))
4566  Xclose
4567
4568  if a:cchar == 'l'
4569    %bwipe
4570    " For a location list, when both the file window and the location list
4571    " window for the list are closed, then the buffer should be freed.
4572    new | only
4573    lexpr "F1:10:Line10"
4574    let wid = win_getid()
4575    lopen
4576    let qfbnum = bufnr('')
4577    call assert_match(qfbnum . ' %a-  "\[Location List]"', execute('ls'))
4578    close
4579    " When the location list window is closed, the buffer name should not
4580    " change to 'Quickfix List'
4581    call assert_match(qfbnum . 'u h-  "\[Location List]"', execute('ls!'))
4582    call assert_true(bufloaded(qfbnum))
4583
4584    " After deleting a location list buffer using ":bdelete", opening the
4585    " location list window should mark the buffer as a location list buffer.
4586    exe "bdelete " . qfbnum
4587    lopen
4588    call assert_equal("quickfix", &buftype)
4589    call assert_equal(1, getwininfo(win_getid(winnr()))[0].loclist)
4590    call assert_equal(wid, getloclist(0, {'filewinid' : 0}).filewinid)
4591    call assert_false(&swapfile)
4592    lclose
4593
4594    " When the location list is cleared for the window, the buffer should be
4595    " removed
4596    call setloclist(0, [], 'f')
4597    call assert_false(bufexists(qfbnum))
4598    call assert_equal(0, getloclist(0, {'qfbufnr' : 0}).qfbufnr)
4599
4600    " When the location list is freed with the location list window open, the
4601    " location list buffer should not be lost. It should be reused when the
4602    " location list is again populated.
4603    lexpr "F1:10:Line10"
4604    lopen
4605    let wid = win_getid()
4606    let qfbnum = bufnr('')
4607    wincmd p
4608    call setloclist(0, [], 'f')
4609    lexpr "F1:10:Line10"
4610    lopen
4611    call assert_equal(wid, win_getid())
4612    call assert_equal(qfbnum, bufnr(''))
4613    lclose
4614
4615    " When the window with the location list is closed, the buffer should be
4616    " removed
4617    new | only
4618    call assert_false(bufexists(qfbnum))
4619  endif
4620endfunc
4621
4622func Test_qfbuf()
4623  call Xqfbuf_test('c')
4624  call Xqfbuf_test('l')
4625endfunc
4626
4627" If there is an autocmd to use only one window, then opening the location
4628" list window used to crash Vim.
4629func Test_winonly_autocmd()
4630  call s:create_test_file('Xtest1')
4631  " Autocmd to show only one Vim window at a time
4632  autocmd WinEnter * only
4633  new
4634  " Load the location list
4635  lexpr "Xtest1:5:Line5\nXtest1:10:Line10\nXtest1:15:Line15"
4636  let loclistid = getloclist(0, {'id' : 0}).id
4637  " Open the location list window. Only this window will be shown and the file
4638  " window is closed.
4639  lopen
4640  call assert_equal(loclistid, getloclist(0, {'id' : 0}).id)
4641  " Jump to an entry in the location list and make sure that the cursor is
4642  " positioned correctly.
4643  ll 3
4644  call assert_equal(loclistid, getloclist(0, {'id' : 0}).id)
4645  call assert_equal('Xtest1', @%)
4646  call assert_equal(15, line('.'))
4647  " Cleanup
4648  autocmd! WinEnter
4649  new | only
4650  call delete('Xtest1')
4651endfunc
4652
4653" Test to make sure that an empty quickfix buffer is not reused for loading
4654" a normal buffer.
4655func Test_empty_qfbuf()
4656  enew | only
4657  call writefile(["Test"], 'Xfile1')
4658  call setqflist([], 'f')
4659  copen | only
4660  let qfbuf = bufnr('')
4661  edit Xfile1
4662  call assert_notequal(qfbuf, bufnr(''))
4663  enew
4664  call delete('Xfile1')
4665endfunc
4666
4667" Test for the :cbelow, :cabove, :lbelow and :labove commands.
4668" And for the :cafter, :cbefore, :lafter and :lbefore commands.
4669func Xtest_below(cchar)
4670  call s:setup_commands(a:cchar)
4671
4672  " No quickfix/location list
4673  call assert_fails('Xbelow', 'E42:')
4674  call assert_fails('Xabove', 'E42:')
4675  call assert_fails('Xbefore', 'E42:')
4676  call assert_fails('Xafter', 'E42:')
4677
4678  " Empty quickfix/location list
4679  call g:Xsetlist([])
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  call s:create_test_file('X1')
4686  call s:create_test_file('X2')
4687  call s:create_test_file('X3')
4688  call s:create_test_file('X4')
4689
4690  " Invalid entries
4691  edit X1
4692  call g:Xsetlist(["E1", "E2"])
4693  call assert_fails('Xbelow', 'E42:')
4694  call assert_fails('Xabove', 'E42:')
4695  call assert_fails('3Xbelow', 'E42:')
4696  call assert_fails('4Xabove', 'E42:')
4697  call assert_fails('Xbefore', 'E42:')
4698  call assert_fails('Xafter', 'E42:')
4699  call assert_fails('3Xbefore', 'E42:')
4700  call assert_fails('4Xafter', 'E42:')
4701
4702  " Test the commands with various arguments
4703  Xexpr ["X1:5:3:L5", "X2:5:2:L5", "X2:10:3:L10", "X2:15:4:L15", "X3:3:5:L3"]
4704  edit +7 X2
4705  Xabove
4706  call assert_equal(['X2', 5], [@%, line('.')])
4707  call assert_fails('Xabove', 'E553:')
4708  normal 7G
4709  Xbefore
4710  call assert_equal(['X2', 5, 2], [@%, line('.'), col('.')])
4711  call assert_fails('Xbefore', 'E553:')
4712
4713  normal 2j
4714  Xbelow
4715  call assert_equal(['X2', 10], [@%, line('.')])
4716  normal 7G
4717  Xafter
4718  call assert_equal(['X2', 10, 3], [@%, line('.'), col('.')])
4719
4720  " Last error in this file
4721  Xbelow 99
4722  call assert_equal(['X2', 15], [@%, line('.')])
4723  call assert_fails('Xbelow', 'E553:')
4724  normal gg
4725  Xafter 99
4726  call assert_equal(['X2', 15, 4], [@%, line('.'), col('.')])
4727  call assert_fails('Xafter', 'E553:')
4728
4729  " First error in this file
4730  Xabove 99
4731  call assert_equal(['X2', 5], [@%, line('.')])
4732  call assert_fails('Xabove', 'E553:')
4733  normal G
4734  Xbefore 99
4735  call assert_equal(['X2', 5, 2], [@%, line('.'), col('.')])
4736  call assert_fails('Xbefore', 'E553:')
4737
4738  normal gg
4739  Xbelow 2
4740  call assert_equal(['X2', 10], [@%, line('.')])
4741  normal gg
4742  Xafter 2
4743  call assert_equal(['X2', 10, 3], [@%, line('.'), col('.')])
4744
4745  normal G
4746  Xabove 2
4747  call assert_equal(['X2', 10], [@%, line('.')])
4748  normal G
4749  Xbefore 2
4750  call assert_equal(['X2', 10, 3], [@%, line('.'), col('.')])
4751
4752  edit X4
4753  call assert_fails('Xabove', 'E42:')
4754  call assert_fails('Xbelow', 'E42:')
4755  call assert_fails('Xbefore', 'E42:')
4756  call assert_fails('Xafter', 'E42:')
4757  if a:cchar == 'l'
4758    " If a buffer has location list entries from some other window but not
4759    " from the current window, then the commands should fail.
4760    edit X1 | split | call setloclist(0, [], 'f')
4761    call assert_fails('Xabove', 'E776:')
4762    call assert_fails('Xbelow', 'E776:')
4763    call assert_fails('Xbefore', 'E776:')
4764    call assert_fails('Xafter', 'E776:')
4765    close
4766  endif
4767
4768  " Test for lines with multiple quickfix entries
4769  Xexpr ["X1:5:L5", "X2:5:1:L5_1", "X2:5:2:L5_2", "X2:5:3:L5_3",
4770	      \ "X2:10:1:L10_1", "X2:10:2:L10_2", "X2:10:3:L10_3",
4771	      \ "X2:15:1:L15_1", "X2:15:2:L15_2", "X2:15:3:L15_3", "X3:3:L3"]
4772  edit +1 X2
4773  Xbelow 2
4774  call assert_equal(['X2', 10, 1], [@%, line('.'), col('.')])
4775  normal 1G
4776  Xafter 2
4777  call assert_equal(['X2', 5, 2], [@%, line('.'), col('.')])
4778
4779  normal gg
4780  Xbelow 99
4781  call assert_equal(['X2', 15, 1], [@%, line('.'), col('.')])
4782  normal gg
4783  Xafter 99
4784  call assert_equal(['X2', 15, 3], [@%, line('.'), col('.')])
4785
4786  normal G
4787  Xabove 2
4788  call assert_equal(['X2', 10, 1], [@%, line('.'), col('.')])
4789  normal G
4790  Xbefore 2
4791  call assert_equal(['X2', 15, 2], [@%, line('.'), col('.')])
4792
4793  normal G
4794  Xabove 99
4795  call assert_equal(['X2', 5, 1], [@%, line('.'), col('.')])
4796  normal G
4797  Xbefore 99
4798  call assert_equal(['X2', 5, 1], [@%, line('.'), col('.')])
4799
4800  normal 10G
4801  Xabove
4802  call assert_equal(['X2', 5, 1], [@%, line('.'), col('.')])
4803  normal 10G$
4804  2Xbefore
4805  call assert_equal(['X2', 10, 2], [@%, line('.'), col('.')])
4806
4807  normal 10G
4808  Xbelow
4809  call assert_equal(['X2', 15, 1], [@%, line('.'), col('.')])
4810  normal 9G
4811  5Xafter
4812  call assert_equal(['X2', 15, 2], [@%, line('.'), col('.')])
4813
4814  " Invalid range
4815  if a:cchar == 'c'
4816    call assert_fails('-2cbelow', 'E16:')
4817    call assert_fails('-2cafter', 'E16:')
4818  else
4819    call assert_fails('-2lbelow', 'E16:')
4820    call assert_fails('-2lafter', 'E16:')
4821  endif
4822
4823  call delete('X1')
4824  call delete('X2')
4825  call delete('X3')
4826  call delete('X4')
4827endfunc
4828
4829func Test_cbelow()
4830  call Xtest_below('c')
4831  call Xtest_below('l')
4832endfunc
4833
4834func Test_quickfix_count()
4835  let commands = [
4836	\ 'cNext',
4837	\ 'cNfile',
4838	\ 'cabove',
4839	\ 'cbelow',
4840	\ 'cfirst',
4841	\ 'clast',
4842	\ 'cnewer',
4843	\ 'cnext',
4844	\ 'cnfile',
4845	\ 'colder',
4846	\ 'cprevious',
4847	\ 'crewind',
4848	\
4849	\ 'lNext',
4850	\ 'lNfile',
4851	\ 'labove',
4852	\ 'lbelow',
4853	\ 'lfirst',
4854	\ 'llast',
4855	\ 'lnewer',
4856	\ 'lnext',
4857	\ 'lnfile',
4858	\ 'lolder',
4859	\ 'lprevious',
4860	\ 'lrewind',
4861	\ ]
4862  for cmd in commands
4863    call assert_fails('-1' .. cmd, 'E16:')
4864    call assert_fails('.' .. cmd, 'E16:')
4865    call assert_fails('%' .. cmd, 'E16:')
4866    call assert_fails('$' .. cmd, 'E16:')
4867  endfor
4868endfunc
4869
4870" Test for aborting quickfix commands using QuickFixCmdPre
4871func Xtest_qfcmd_abort(cchar)
4872  call s:setup_commands(a:cchar)
4873
4874  call g:Xsetlist([], 'f')
4875
4876  " cexpr/lexpr
4877  let e = ''
4878  try
4879    Xexpr ["F1:10:Line10", "F2:20:Line20"]
4880  catch /.*/
4881    let e = v:exception
4882  endtry
4883  call assert_equal('AbortCmd', e)
4884  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4885
4886  " cfile/lfile
4887  call writefile(["F1:10:Line10", "F2:20:Line20"], 'Xfile1')
4888  let e = ''
4889  try
4890    Xfile Xfile1
4891  catch /.*/
4892    let e = v:exception
4893  endtry
4894  call assert_equal('AbortCmd', e)
4895  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4896  call delete('Xfile1')
4897
4898  " cgetbuffer/lgetbuffer
4899  enew!
4900  call append(0, ["F1:10:Line10", "F2:20:Line20"])
4901  let e = ''
4902  try
4903    Xgetbuffer
4904  catch /.*/
4905    let e = v:exception
4906  endtry
4907  call assert_equal('AbortCmd', e)
4908  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4909  enew!
4910
4911  " vimgrep/lvimgrep
4912  let e = ''
4913  try
4914    Xvimgrep /func/ test_quickfix.vim
4915  catch /.*/
4916    let e = v:exception
4917  endtry
4918  call assert_equal('AbortCmd', e)
4919  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4920
4921  " helpgrep/lhelpgrep
4922  let e = ''
4923  try
4924    Xhelpgrep quickfix
4925  catch /.*/
4926    let e = v:exception
4927  endtry
4928  call assert_equal('AbortCmd', e)
4929  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4930
4931  " grep/lgrep
4932  if has('unix')
4933    let e = ''
4934    try
4935      silent Xgrep func test_quickfix.vim
4936    catch /.*/
4937      let e = v:exception
4938    endtry
4939    call assert_equal('AbortCmd', e)
4940    call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4941  endif
4942endfunc
4943
4944func Test_qfcmd_abort()
4945  augroup QF_Test
4946    au!
4947    autocmd  QuickFixCmdPre * throw "AbortCmd"
4948  augroup END
4949
4950  call Xtest_qfcmd_abort('c')
4951  call Xtest_qfcmd_abort('l')
4952
4953  augroup QF_Test
4954    au!
4955  augroup END
4956endfunc
4957
4958" Test for using a file in one of the parent directories.
4959func Test_search_in_dirstack()
4960  call mkdir('Xtestdir/a/b/c', 'p')
4961  let save_cwd = getcwd()
4962  call writefile(["X1_L1", "X1_L2"], 'Xtestdir/Xfile1')
4963  call writefile(["X2_L1", "X2_L2"], 'Xtestdir/a/Xfile2')
4964  call writefile(["X3_L1", "X3_L2"], 'Xtestdir/a/b/Xfile3')
4965  call writefile(["X4_L1", "X4_L2"], 'Xtestdir/a/b/c/Xfile4')
4966
4967  let lines = "Entering dir Xtestdir\n" .
4968	      \ "Entering dir a\n" .
4969	      \ "Entering dir b\n" .
4970	      \ "Xfile2:2:X2_L2\n" .
4971	      \ "Leaving dir a\n" .
4972	      \ "Xfile1:2:X1_L2\n" .
4973	      \ "Xfile3:1:X3_L1\n" .
4974	      \ "Entering dir c\n" .
4975	      \ "Xfile4:2:X4_L2\n" .
4976	      \ "Leaving dir c\n"
4977  set efm=%DEntering\ dir\ %f,%XLeaving\ dir\ %f,%f:%l:%m
4978  cexpr lines .. "Leaving dir Xtestdir|\n" | let next = 1
4979  call assert_equal(11, getqflist({'size' : 0}).size)
4980  call assert_equal(4, getqflist({'idx' : 0}).idx)
4981  call assert_equal('X2_L2', getline('.'))
4982  call assert_equal(1, next)
4983  cnext
4984  call assert_equal(6, getqflist({'idx' : 0}).idx)
4985  call assert_equal('X1_L2', getline('.'))
4986  cnext
4987  call assert_equal(7, getqflist({'idx' : 0}).idx)
4988  call assert_equal(1, line('$'))
4989  call assert_equal('', getline(1))
4990  cnext
4991  call assert_equal(9, getqflist({'idx' : 0}).idx)
4992  call assert_equal(1, line('$'))
4993  call assert_equal('', getline(1))
4994
4995  set efm&
4996  exe 'cd ' . save_cwd
4997  call delete('Xtestdir', 'rf')
4998endfunc
4999
5000" Test for :cquit
5001func Test_cquit()
5002  " Exit Vim with a non-zero value
5003  if RunVim([], ["cquit 7"], '')
5004    call assert_equal(7, v:shell_error)
5005  endif
5006
5007  if RunVim([], ["50cquit"], '')
5008    call assert_equal(50, v:shell_error)
5009  endif
5010
5011  " Exit Vim with default value
5012  if RunVim([], ["cquit"], '')
5013    call assert_equal(1, v:shell_error)
5014  endif
5015
5016  " Exit Vim with zero value
5017  if RunVim([], ["cquit 0"], '')
5018    call assert_equal(0, v:shell_error)
5019  endif
5020
5021  " Exit Vim with negative value
5022  call assert_fails('-3cquit', 'E16:')
5023endfunc
5024
5025" Test for getting a specific item from a quickfix list
5026func Xtest_getqflist_by_idx(cchar)
5027  call s:setup_commands(a:cchar)
5028  " Empty list
5029  call assert_equal([], g:Xgetlist({'idx' : 1, 'items' : 0}).items)
5030  Xexpr ['F1:10:L10', 'F1:20:L20']
5031  let l = g:Xgetlist({'idx' : 2, 'items' : 0}).items
5032  call assert_equal(bufnr('F1'), l[0].bufnr)
5033  call assert_equal(20, l[0].lnum)
5034  call assert_equal('L20', l[0].text)
5035  call assert_equal([], g:Xgetlist({'idx' : -1, 'items' : 0}).items)
5036  call assert_equal([], g:Xgetlist({'idx' : 3, 'items' : 0}).items)
5037  %bwipe!
5038endfunc
5039
5040func Test_getqflist_by_idx()
5041  call Xtest_getqflist_by_idx('c')
5042  call Xtest_getqflist_by_idx('l')
5043endfunc
5044
5045" Test for the 'quickfixtextfunc' setting
5046func Tqfexpr(info)
5047  if a:info.quickfix
5048    let qfl = getqflist({'id' : a:info.id, 'items' : 1}).items
5049  else
5050    let qfl = getloclist(a:info.winid, {'id' : a:info.id, 'items' : 1}).items
5051  endif
5052
5053  let l = []
5054  for idx in range(a:info.start_idx - 1, a:info.end_idx - 1)
5055    let e = qfl[idx]
5056    let s = ''
5057    if e.bufnr != 0
5058      let bname = bufname(e.bufnr)
5059      let s ..= fnamemodify(bname, ':.')
5060    endif
5061    let s ..= '-'
5062    let s ..= 'L' .. string(e.lnum) .. 'C' .. string(e.col) .. '-'
5063    let s ..= e.text
5064    call add(l, s)
5065  endfor
5066
5067  return l
5068endfunc
5069
5070func Xtest_qftextfunc(cchar)
5071  call s:setup_commands(a:cchar)
5072
5073  set efm=%f:%l:%c:%m
5074  set quickfixtextfunc=Tqfexpr
5075  call assert_equal('Tqfexpr', &quickfixtextfunc)
5076  call assert_equal('',
5077        \ g:Xgetlist({'quickfixtextfunc' : 1}).quickfixtextfunc)
5078  Xexpr ['F1:10:2:green', 'F1:20:4:blue']
5079  Xwindow
5080  call assert_equal('F1-L10C2-green', getline(1))
5081  call assert_equal('F1-L20C4-blue', getline(2))
5082  Xclose
5083  set quickfixtextfunc&vim
5084  Xwindow
5085  call assert_equal('F1|10 col 2| green', getline(1))
5086  call assert_equal('F1|20 col 4| blue', getline(2))
5087  Xclose
5088  set efm&
5089  set quickfixtextfunc&
5090
5091  " Test for per list 'quickfixtextfunc' setting
5092  func PerQfText(info)
5093    if a:info.quickfix
5094      let qfl = getqflist({'id' : a:info.id, 'items' : 1}).items
5095    else
5096      let qfl = getloclist(a:info.winid, {'id' : a:info.id, 'items' : 1}).items
5097    endif
5098    if empty(qfl)
5099      return []
5100    endif
5101    let l = []
5102    for idx in range(a:info.start_idx - 1, a:info.end_idx - 1)
5103      call add(l, 'Line ' .. qfl[idx].lnum .. ', Col ' .. qfl[idx].col)
5104    endfor
5105    return l
5106  endfunc
5107  set quickfixtextfunc=Tqfexpr
5108  call g:Xsetlist([], ' ', {'quickfixtextfunc' : "PerQfText"})
5109  Xaddexpr ['F1:10:2:green', 'F1:20:4:blue']
5110  Xwindow
5111  call assert_equal('Line 10, Col 2', getline(1))
5112  call assert_equal('Line 20, Col 4', getline(2))
5113  Xclose
5114  call assert_equal(function('PerQfText'),
5115        \ g:Xgetlist({'quickfixtextfunc' : 1}).quickfixtextfunc)
5116  " Add entries to the list when the quickfix buffer is hidden
5117  Xaddexpr ['F1:30:6:red']
5118  Xwindow
5119  call assert_equal('Line 30, Col 6', getline(3))
5120  Xclose
5121  call g:Xsetlist([], 'r', {'quickfixtextfunc' : ''})
5122  call assert_equal('', g:Xgetlist({'quickfixtextfunc' : 1}).quickfixtextfunc)
5123  set quickfixtextfunc&
5124  delfunc PerQfText
5125
5126  " Non-existing function
5127  set quickfixtextfunc=Tabc
5128  call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue']", 'E117:')
5129  call assert_fails("Xwindow", 'E117:')
5130  Xclose
5131  set quickfixtextfunc&
5132
5133  " set option to a non-function
5134  set quickfixtextfunc=[10,\ 20]
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 function with different set of arguments
5141  func Xqftext(a, b, c)
5142    return a:a .. a:b .. a:c
5143  endfunc
5144  set quickfixtextfunc=Xqftext
5145  call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue']", 'E119:')
5146  call assert_fails("Xwindow", 'E119:')
5147  Xclose
5148
5149  " set option to a function that returns a list with non-strings
5150  func Xqftext2(d)
5151    return ['one', [], 'two']
5152  endfunc
5153  set quickfixtextfunc=Xqftext2
5154  call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue', 'F1:30:6:red']",
5155                                                                  \ 'E730:')
5156  call assert_fails('Xwindow', 'E730:')
5157  call assert_equal(['one', 'F1|20 col 4| blue', 'F1|30 col 6| red'],
5158        \ getline(1, '$'))
5159  Xclose
5160
5161  set quickfixtextfunc&
5162  delfunc Xqftext
5163  delfunc Xqftext2
5164
5165  " set the global option to a lambda function
5166  set quickfixtextfunc={d\ ->\ map(g:Xgetlist({'id'\ :\ d.id,\ 'items'\ :\ 1}).items[d.start_idx-1:d.end_idx-1],\ 'v:val.text')}
5167  Xexpr ['F1:10:2:green', 'F1:20:4:blue']
5168  Xwindow
5169  call assert_equal(['green', 'blue'], getline(1, '$'))
5170  Xclose
5171  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)
5172  set quickfixtextfunc&
5173
5174  " use a lambda function that returns an empty list
5175  set quickfixtextfunc={d\ ->\ []}
5176  Xexpr ['F1:10:2:green', 'F1:20:4:blue']
5177  Xwindow
5178  call assert_equal(['F1|10 col 2| green', 'F1|20 col 4| blue'],
5179        \ getline(1, '$'))
5180  Xclose
5181  set quickfixtextfunc&
5182
5183  " use a lambda function that returns a list with empty strings
5184  set quickfixtextfunc={d\ ->\ ['',\ '']}
5185  Xexpr ['F1:10:2:green', 'F1:20:4:blue']
5186  Xwindow
5187  call assert_equal(['F1|10 col 2| green', 'F1|20 col 4| blue'],
5188        \ getline(1, '$'))
5189  Xclose
5190  set quickfixtextfunc&
5191
5192  " set the per-quickfix list text function to a lambda function
5193  call g:Xsetlist([], ' ',
5194        \ {'quickfixtextfunc' :
5195        \   {d -> map(g:Xgetlist({'id' : d.id, 'items' : 1}).items[d.start_idx-1:d.end_idx-1],
5196        \ "'Line ' .. v:val.lnum .. ', Col ' .. v:val.col")}})
5197  Xaddexpr ['F1:10:2:green', 'F1:20:4:blue']
5198  Xwindow
5199  call assert_equal('Line 10, Col 2', getline(1))
5200  call assert_equal('Line 20, Col 4', getline(2))
5201  Xclose
5202  call assert_match("function('<lambda>\\d\\+')", string(g:Xgetlist({'quickfixtextfunc' : 1}).quickfixtextfunc))
5203  call g:Xsetlist([], 'f')
5204endfunc
5205
5206func Test_qftextfunc()
5207  call Xtest_qftextfunc('c')
5208  call Xtest_qftextfunc('l')
5209endfunc
5210
5211" Running :lhelpgrep command more than once in a help window, doesn't jump to
5212" the help topic
5213func Test_lhelpgrep_from_help_window()
5214  call mkdir('Xtestdir/doc', 'p')
5215  call writefile(['window'], 'Xtestdir/doc/a.txt')
5216  call writefile(['buffer'], 'Xtestdir/doc/b.txt')
5217  let save_rtp = &rtp
5218  let &rtp = 'Xtestdir'
5219  lhelpgrep window
5220  lhelpgrep buffer
5221  call assert_equal('b.txt', fnamemodify(@%, ":p:t"))
5222  lhelpgrep window
5223  call assert_equal('a.txt', fnamemodify(@%, ":p:t"))
5224  let &rtp = save_rtp
5225  call delete('Xtestdir', 'rf')
5226  new | only!
5227endfunc
5228
5229" Test for the crash fixed by 7.3.715
5230func Test_setloclist_crash()
5231  %bw!
5232  let g:BufNum = bufnr()
5233  augroup QF_Test
5234    au!
5235    au BufUnload * call setloclist(0, [{'bufnr':g:BufNum, 'lnum':1, 'col':1, 'text': 'tango down'}])
5236  augroup END
5237
5238  try
5239    lvimgrep /.*/ *.mak
5240  catch /E926:/
5241  endtry
5242  call assert_equal('tango down', getloclist(0, {'items' : 0}).items[0].text)
5243  call assert_equal(1, getloclist(0, {'size' : 0}).size)
5244
5245  augroup QF_Test
5246    au!
5247  augroup END
5248  unlet g:BufNum
5249  %bw!
5250endfunc
5251
5252" Test for adding an invalid entry with the quickfix window open and making
5253" sure that the window contents are not changed
5254func Test_add_invalid_entry_with_qf_window()
5255  call setqflist([], 'f')
5256  cexpr "Xfile1:10:aa"
5257  copen
5258  call setqflist(['bb'], 'a')
5259  call assert_equal(1, line('$'))
5260  call assert_equal(['Xfile1|10| aa'], getline(1, '$'))
5261  call assert_equal([{'lnum': 10, 'bufnr': bufnr('Xfile1'), 'col': 0, 'pattern': '', 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'module': '', 'text': 'aa'}], getqflist())
5262  cclose
5263endfunc
5264
5265" Test for very weird problem: autocommand causes a failure, resulting opening
5266" the quickfix window to fail. This still splits the window, but otherwise
5267" should not mess up buffers.
5268func Test_quickfix_window_fails_to_open()
5269  CheckScreendump
5270
5271  let lines =<< trim END
5272      anything
5273      try
5274        anything
5275      endtry
5276  END
5277  call writefile(lines, 'XquickfixFails')
5278
5279  let lines =<< trim END
5280      split XquickfixFails
5281      silent vimgrep anything %
5282      normal o
5283      au BufLeave * ++once source XquickfixFails
5284      " This will trigger the autocommand, which causes an error, what follows
5285      " is aborted but the window was already split.
5286      silent! cwindow
5287  END
5288  call writefile(lines, 'XtestWinFails')
5289  let buf = RunVimInTerminal('-S XtestWinFails', #{rows: 13})
5290  call VerifyScreenDump(buf, 'Test_quickfix_window_fails', {})
5291
5292  " clean up
5293  call term_sendkeys(buf, ":bwipe!\<CR>")
5294  call term_wait(buf)
5295  call StopVimInTerminal(buf)
5296  call delete('XtestWinFails')
5297  call delete('XquickfixFails')
5298endfunc
5299
5300" Test for updating the quickfix buffer whenever the associated quickfix list
5301" is changed.
5302func Xqfbuf_update(cchar)
5303  call s:setup_commands(a:cchar)
5304
5305  Xexpr "F1:1:line1"
5306  Xopen
5307  call assert_equal(['F1|1| line1'], getline(1, '$'))
5308  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
5309
5310  " Test setqflist() using the 'lines' key in 'what'
5311  " add a new entry
5312  call g:Xsetlist([], 'a', {'lines' : ['F2:2: line2']})
5313  call assert_equal(['F1|1| line1', 'F2|2| line2'], getline(1, '$'))
5314  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
5315  " replace all the entries with a single entry
5316  call g:Xsetlist([], 'r', {'lines' : ['F3:3: line3']})
5317  call assert_equal(['F3|3| line3'], getline(1, '$'))
5318  call assert_equal(3, g:Xgetlist({'changedtick' : 0}).changedtick)
5319  " remove all the entries
5320  call g:Xsetlist([], 'r', {'lines' : []})
5321  call assert_equal([''], getline(1, '$'))
5322  call assert_equal(4, g:Xgetlist({'changedtick' : 0}).changedtick)
5323  " add a new list
5324  call g:Xsetlist([], ' ', {'lines' : ['F4:4: line4']})
5325  call assert_equal(['F4|4| line4'], getline(1, '$'))
5326  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
5327
5328  " Test setqflist() using the 'items' key in 'what'
5329  " add a new entry
5330  call g:Xsetlist([], 'a', {'items' : [{'filename' : 'F5', 'lnum' : 5, 'text' : 'line5'}]})
5331  call assert_equal(['F4|4| line4', 'F5|5| line5'], getline(1, '$'))
5332  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
5333  " replace all the entries with a single entry
5334  call g:Xsetlist([], 'r', {'items' : [{'filename' : 'F6', 'lnum' : 6, 'text' : 'line6'}]})
5335  call assert_equal(['F6|6| line6'], getline(1, '$'))
5336  call assert_equal(3, g:Xgetlist({'changedtick' : 0}).changedtick)
5337  " remove all the entries
5338  call g:Xsetlist([], 'r', {'items' : []})
5339  call assert_equal([''], getline(1, '$'))
5340  call assert_equal(4, g:Xgetlist({'changedtick' : 0}).changedtick)
5341  " add a new list
5342  call g:Xsetlist([], ' ', {'items' : [{'filename' : 'F7', 'lnum' : 7, 'text' : 'line7'}]})
5343  call assert_equal(['F7|7| line7'], getline(1, '$'))
5344  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
5345
5346  call g:Xsetlist([], ' ', {})
5347  call assert_equal([''], getline(1, '$'))
5348  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
5349
5350  Xclose
5351endfunc
5352
5353func Test_qfbuf_update()
5354  call Xqfbuf_update('c')
5355  call Xqfbuf_update('l')
5356endfunc
5357
5358" vim: shiftwidth=2 sts=2 expandtab
5359