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