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