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_caddbuffer_to_empty()
1434  helpgr quickfix
1435  call setqflist([], 'r')
1436  cad
1437  try
1438    cn
1439  catch
1440    " number of matches is unknown
1441    call assert_true(v:exception =~ 'E553:')
1442  endtry
1443  quit!
1444endfunc
1445
1446func Test_cgetexpr_works()
1447  " this must not crash Vim
1448  cgetexpr [$x]
1449  lgetexpr [$x]
1450endfunc
1451
1452" Tests for the setqflist() and setloclist() functions
1453func SetXlistTests(cchar, bnum)
1454  call s:setup_commands(a:cchar)
1455
1456  call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 1},
1457	      \  {'bufnr': a:bnum, 'lnum': 2}])
1458  let l = g:Xgetlist()
1459  call assert_equal(2, len(l))
1460  call assert_equal(2, l[1].lnum)
1461
1462  Xnext
1463  call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 3}], 'a')
1464  let l = g:Xgetlist()
1465  call assert_equal(3, len(l))
1466  Xnext
1467  call assert_equal(3, line('.'))
1468
1469  " Appending entries to the list should not change the cursor position
1470  " in the quickfix window
1471  Xwindow
1472  1
1473  call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 4},
1474	      \  {'bufnr': a:bnum, 'lnum': 5}], 'a')
1475  call assert_equal(1, line('.'))
1476  close
1477
1478  call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 3},
1479	      \  {'bufnr': a:bnum, 'lnum': 4},
1480	      \  {'bufnr': a:bnum, 'lnum': 5}], 'r')
1481  let l = g:Xgetlist()
1482  call assert_equal(3, len(l))
1483  call assert_equal(5, l[2].lnum)
1484
1485  call g:Xsetlist([])
1486  let l = g:Xgetlist()
1487  call assert_equal(0, len(l))
1488
1489  " Tests for setting the 'valid' flag
1490  call g:Xsetlist([{'bufnr':a:bnum, 'lnum':4, 'valid':0}])
1491  Xwindow
1492  call assert_equal(1, winnr('$'))
1493  let l = g:Xgetlist()
1494  call g:Xsetlist(l)
1495  call assert_equal(0, g:Xgetlist()[0].valid)
1496  " Adding a non-valid entry should not mark the list as having valid entries
1497  call g:Xsetlist([{'bufnr':a:bnum, 'lnum':5, 'valid':0}], 'a')
1498  Xwindow
1499  call assert_equal(1, winnr('$'))
1500
1501  " :cnext/:cprev should still work even with invalid entries in the list
1502  let l = [{'bufnr' : a:bnum, 'lnum' : 1, 'text' : '1', 'valid' : 0},
1503	      \ {'bufnr' : a:bnum, 'lnum' : 2, 'text' : '2', 'valid' : 0}]
1504  call g:Xsetlist(l)
1505  Xnext
1506  call assert_equal(2, g:Xgetlist({'idx' : 0}).idx)
1507  Xprev
1508  call assert_equal(1, g:Xgetlist({'idx' : 0}).idx)
1509  " :cnext/:cprev should still work after appending invalid entries to an
1510  " empty list
1511  call g:Xsetlist([])
1512  call g:Xsetlist(l, 'a')
1513  Xnext
1514  call assert_equal(2, g:Xgetlist({'idx' : 0}).idx)
1515  Xprev
1516  call assert_equal(1, g:Xgetlist({'idx' : 0}).idx)
1517
1518  call g:Xsetlist([{'text':'Text1', 'valid':1}])
1519  Xwindow
1520  call assert_equal(2, winnr('$'))
1521  Xclose
1522  let save_efm = &efm
1523  set efm=%m
1524  Xgetexpr 'TestMessage'
1525  let l = g:Xgetlist()
1526  call g:Xsetlist(l)
1527  call assert_equal(1, g:Xgetlist()[0].valid)
1528  let &efm = save_efm
1529
1530  " Error cases:
1531  " Refer to a non-existing buffer and pass a non-dictionary type
1532  call assert_fails("call g:Xsetlist([{'bufnr':998, 'lnum':4}," .
1533	      \ " {'bufnr':999, 'lnum':5}])", 'E92:')
1534  call g:Xsetlist([[1, 2,3]])
1535  call assert_equal(0, len(g:Xgetlist()))
1536  call assert_fails('call g:Xsetlist([], [])', 'E928:')
1537endfunc
1538
1539func Test_setqflist()
1540  new Xtestfile | only
1541  let bnum = bufnr('%')
1542  call setline(1, range(1,5))
1543
1544  call SetXlistTests('c', bnum)
1545  call SetXlistTests('l', bnum)
1546
1547  enew!
1548  call delete('Xtestfile')
1549endfunc
1550
1551func Xlist_empty_middle(cchar)
1552  call s:setup_commands(a:cchar)
1553
1554  " create three quickfix lists
1555  let @/ = 'Test_'
1556  Xvimgrep // test_quickfix.vim
1557  let testlen = len(g:Xgetlist())
1558  call assert_true(testlen > 0)
1559  Xvimgrep empty test_quickfix.vim
1560  call assert_true(len(g:Xgetlist()) > 0)
1561  Xvimgrep matches test_quickfix.vim
1562  let matchlen = len(g:Xgetlist())
1563  call assert_true(matchlen > 0)
1564  Xolder
1565  " make the middle list empty
1566  call g:Xsetlist([], 'r')
1567  call assert_true(len(g:Xgetlist()) == 0)
1568  Xolder
1569  call assert_equal(testlen, len(g:Xgetlist()))
1570  Xnewer
1571  Xnewer
1572  call assert_equal(matchlen, len(g:Xgetlist()))
1573endfunc
1574
1575func Test_setqflist_empty_middle()
1576  call Xlist_empty_middle('c')
1577  call Xlist_empty_middle('l')
1578endfunc
1579
1580func Xlist_empty_older(cchar)
1581  call s:setup_commands(a:cchar)
1582
1583  " create three quickfix lists
1584  Xvimgrep one test_quickfix.vim
1585  let onelen = len(g:Xgetlist())
1586  call assert_true(onelen > 0)
1587  Xvimgrep two test_quickfix.vim
1588  let twolen = len(g:Xgetlist())
1589  call assert_true(twolen > 0)
1590  Xvimgrep three test_quickfix.vim
1591  let threelen = len(g:Xgetlist())
1592  call assert_true(threelen > 0)
1593  Xolder 2
1594  " make the first list empty, check the others didn't change
1595  call g:Xsetlist([], 'r')
1596  call assert_true(len(g:Xgetlist()) == 0)
1597  Xnewer
1598  call assert_equal(twolen, len(g:Xgetlist()))
1599  Xnewer
1600  call assert_equal(threelen, len(g:Xgetlist()))
1601endfunc
1602
1603func Test_setqflist_empty_older()
1604  call Xlist_empty_older('c')
1605  call Xlist_empty_older('l')
1606endfunc
1607
1608func XquickfixSetListWithAct(cchar)
1609  call s:setup_commands(a:cchar)
1610
1611  let list1 = [{'filename': 'fnameA', 'text': 'A'},
1612          \    {'filename': 'fnameB', 'text': 'B'}]
1613  let list2 = [{'filename': 'fnameC', 'text': 'C'},
1614          \    {'filename': 'fnameD', 'text': 'D'},
1615          \    {'filename': 'fnameE', 'text': 'E'}]
1616
1617  " {action} is unspecified.  Same as specifying ' '.
1618  new | only
1619  silent! Xnewer 99
1620  call g:Xsetlist(list1)
1621  call g:Xsetlist(list2)
1622  let li = g:Xgetlist()
1623  call assert_equal(3, len(li))
1624  call assert_equal('C', li[0]['text'])
1625  call assert_equal('D', li[1]['text'])
1626  call assert_equal('E', li[2]['text'])
1627  silent! Xolder
1628  let li = g:Xgetlist()
1629  call assert_equal(2, len(li))
1630  call assert_equal('A', li[0]['text'])
1631  call assert_equal('B', li[1]['text'])
1632
1633  " {action} is specified ' '.
1634  new | only
1635  silent! Xnewer 99
1636  call g:Xsetlist(list1)
1637  call g:Xsetlist(list2, ' ')
1638  let li = g:Xgetlist()
1639  call assert_equal(3, len(li))
1640  call assert_equal('C', li[0]['text'])
1641  call assert_equal('D', li[1]['text'])
1642  call assert_equal('E', li[2]['text'])
1643  silent! Xolder
1644  let li = g:Xgetlist()
1645  call assert_equal(2, len(li))
1646  call assert_equal('A', li[0]['text'])
1647  call assert_equal('B', li[1]['text'])
1648
1649  " {action} is specified 'a'.
1650  new | only
1651  silent! Xnewer 99
1652  call g:Xsetlist(list1)
1653  call g:Xsetlist(list2, 'a')
1654  let li = g:Xgetlist()
1655  call assert_equal(5, len(li))
1656  call assert_equal('A', li[0]['text'])
1657  call assert_equal('B', li[1]['text'])
1658  call assert_equal('C', li[2]['text'])
1659  call assert_equal('D', li[3]['text'])
1660  call assert_equal('E', li[4]['text'])
1661
1662  " {action} is specified 'r'.
1663  new | only
1664  silent! Xnewer 99
1665  call g:Xsetlist(list1)
1666  call g:Xsetlist(list2, 'r')
1667  let li = g:Xgetlist()
1668  call assert_equal(3, len(li))
1669  call assert_equal('C', li[0]['text'])
1670  call assert_equal('D', li[1]['text'])
1671  call assert_equal('E', li[2]['text'])
1672
1673  " Test for wrong value.
1674  new | only
1675  call assert_fails("call g:Xsetlist(0)", 'E714:')
1676  call assert_fails("call g:Xsetlist(list1, '')", 'E927:')
1677  call assert_fails("call g:Xsetlist(list1, 'aa')", 'E927:')
1678  call assert_fails("call g:Xsetlist(list1, ' a')", 'E927:')
1679  call assert_fails("call g:Xsetlist(list1, 0)", 'E928:')
1680endfunc
1681
1682func Test_setqflist_invalid_nr()
1683  " The following command used to crash Vim
1684  eval []->setqflist(' ', {'nr' : $XXX_DOES_NOT_EXIST})
1685endfunc
1686
1687func Test_setqflist_user_sets_buftype()
1688  call setqflist([{'text': 'foo'}, {'text': 'bar'}])
1689  set buftype=quickfix
1690  call setqflist([], 'a')
1691  enew
1692endfunc
1693
1694func Test_quickfix_set_list_with_act()
1695  call XquickfixSetListWithAct('c')
1696  call XquickfixSetListWithAct('l')
1697endfunc
1698
1699func XLongLinesTests(cchar)
1700  let l = g:Xgetlist()
1701
1702  call assert_equal(4, len(l))
1703  call assert_equal(1, l[0].lnum)
1704  call assert_equal(1, l[0].col)
1705  call assert_equal(1975, len(l[0].text))
1706  call assert_equal(2, l[1].lnum)
1707  call assert_equal(1, l[1].col)
1708  call assert_equal(4070, len(l[1].text))
1709  call assert_equal(3, l[2].lnum)
1710  call assert_equal(1, l[2].col)
1711  call assert_equal(4070, len(l[2].text))
1712  call assert_equal(4, l[3].lnum)
1713  call assert_equal(1, l[3].col)
1714  call assert_equal(10, len(l[3].text))
1715
1716  call g:Xsetlist([], 'r')
1717endfunc
1718
1719func s:long_lines_tests(cchar)
1720  call s:setup_commands(a:cchar)
1721
1722  let testfile = 'samples/quickfix.txt'
1723
1724  " file
1725  exe 'Xgetfile' testfile
1726  call XLongLinesTests(a:cchar)
1727
1728  " list
1729  Xexpr readfile(testfile)
1730  call XLongLinesTests(a:cchar)
1731
1732  " string
1733  Xexpr join(readfile(testfile), "\n")
1734  call XLongLinesTests(a:cchar)
1735
1736  " buffer
1737  exe 'edit' testfile
1738  exe 'Xbuffer' bufnr('%')
1739  call XLongLinesTests(a:cchar)
1740endfunc
1741
1742func Test_long_lines()
1743  call s:long_lines_tests('c')
1744  call s:long_lines_tests('l')
1745endfunc
1746
1747func Test_cgetfile_on_long_lines()
1748  " Problematic values if the line is longer than 4096 bytes.  Then 1024 bytes
1749  " are read at a time.
1750  for len in [4078, 4079, 4080, 5102, 5103, 5104, 6126, 6127, 6128, 7150, 7151, 7152]
1751    let lines = [
1752      \ '/tmp/file1:1:1:aaa',
1753      \ '/tmp/file2:1:1:%s',
1754      \ '/tmp/file3:1:1:bbb',
1755      \ '/tmp/file4:1:1:ccc',
1756      \ ]
1757    let lines[1] = substitute(lines[1], '%s', repeat('x', len), '')
1758    call writefile(lines, 'Xcqetfile.txt')
1759    cgetfile Xcqetfile.txt
1760    call assert_equal(4, getqflist(#{size: v:true}).size, 'with length ' .. len)
1761  endfor
1762  call delete('Xcqetfile.txt')
1763endfunc
1764
1765func s:create_test_file(filename)
1766  let l = []
1767  for i in range(1, 20)
1768      call add(l, 'Line' . i)
1769  endfor
1770  call writefile(l, a:filename)
1771endfunc
1772
1773func Test_switchbuf()
1774  call s:create_test_file('Xqftestfile1')
1775  call s:create_test_file('Xqftestfile2')
1776  call s:create_test_file('Xqftestfile3')
1777
1778  new | only
1779  edit Xqftestfile1
1780  let file1_winid = win_getid()
1781  new Xqftestfile2
1782  let file2_winid = win_getid()
1783  cgetexpr ['Xqftestfile1:5:Line5',
1784		\ 'Xqftestfile1:6:Line6',
1785		\ 'Xqftestfile2:10:Line10',
1786		\ 'Xqftestfile2:11:Line11',
1787		\ 'Xqftestfile3:15:Line15',
1788		\ 'Xqftestfile3:16:Line16']
1789
1790  new
1791  let winid = win_getid()
1792  cfirst | cnext
1793  call assert_equal(winid, win_getid())
1794  2cnext
1795  call assert_equal(winid, win_getid())
1796  2cnext
1797  call assert_equal(winid, win_getid())
1798
1799  " Test for 'switchbuf' set to search for files in windows in the current
1800  " tabpage and jump to an existing window (if present)
1801  set switchbuf=useopen
1802  enew
1803  cfirst | cnext
1804  call assert_equal(file1_winid, win_getid())
1805  2cnext
1806  call assert_equal(file2_winid, win_getid())
1807  2cnext
1808  call assert_equal(file2_winid, win_getid())
1809
1810  " Test for 'switchbuf' set to search for files in tabpages and jump to an
1811  " existing tabpage (if present)
1812  enew | only
1813  set switchbuf=usetab
1814  tabedit Xqftestfile1
1815  tabedit Xqftestfile2
1816  tabedit Xqftestfile3
1817  tabfirst
1818  cfirst | cnext
1819  call assert_equal(2, tabpagenr())
1820  2cnext
1821  call assert_equal(3, tabpagenr())
1822  6cnext
1823  call assert_equal(4, tabpagenr())
1824  2cpfile
1825  call assert_equal(2, tabpagenr())
1826  2cnfile
1827  call assert_equal(4, tabpagenr())
1828  tabfirst | tabonly | enew
1829
1830  " Test for 'switchbuf' set to open a new window for every file
1831  set switchbuf=split
1832  cfirst | cnext
1833  call assert_equal(1, winnr('$'))
1834  cnext | cnext
1835  call assert_equal(2, winnr('$'))
1836  cnext | cnext
1837  call assert_equal(3, winnr('$'))
1838
1839  " Test for 'switchbuf' set to open a new tabpage for every file
1840  set switchbuf=newtab
1841  enew | only
1842  cfirst | cnext
1843  call assert_equal(1, tabpagenr('$'))
1844  cnext | cnext
1845  call assert_equal(2, tabpagenr('$'))
1846  cnext | cnext
1847  call assert_equal(3, tabpagenr('$'))
1848  tabfirst | enew | tabonly | only
1849
1850  set switchbuf=uselast
1851  split
1852  let last_winid = win_getid()
1853  copen
1854  exe "normal 1G\<CR>"
1855  call assert_equal(last_winid, win_getid())
1856  enew | only
1857
1858  " With an empty 'switchbuf', jumping to a quickfix entry should open the
1859  " file in an existing window (if present)
1860  set switchbuf=
1861  edit Xqftestfile1
1862  let file1_winid = win_getid()
1863  new Xqftestfile2
1864  let file2_winid = win_getid()
1865  copen
1866  exe "normal 1G\<CR>"
1867  call assert_equal(file1_winid, win_getid())
1868  copen
1869  exe "normal 3G\<CR>"
1870  call assert_equal(file2_winid, win_getid())
1871  copen | only
1872  exe "normal 5G\<CR>"
1873  call assert_equal(2, winnr('$'))
1874  call assert_equal(1, bufwinnr('Xqftestfile3'))
1875
1876  " If only quickfix window is open in the current tabpage, jumping to an
1877  " entry with 'switchbuf' set to 'usetab' should search in other tabpages.
1878  enew | only
1879  set switchbuf=usetab
1880  tabedit Xqftestfile1
1881  tabedit Xqftestfile2
1882  tabedit Xqftestfile3
1883  tabfirst
1884  copen | only
1885  clast
1886  call assert_equal(4, tabpagenr())
1887  tabfirst | tabonly | enew | only
1888
1889  " Jumping to a file that is not present in any of the tabpages and the
1890  " current tabpage doesn't have any usable windows, should open it in a new
1891  " window in the current tabpage.
1892  copen | only
1893  cfirst
1894  call assert_equal(1, tabpagenr())
1895  call assert_equal('Xqftestfile1', @%)
1896
1897  " If opening a file changes 'switchbuf', then the new value should be
1898  " retained.
1899  set modeline&vim
1900  call writefile(["vim: switchbuf=split"], 'Xqftestfile1')
1901  enew | only
1902  set switchbuf&vim
1903  cexpr "Xqftestfile1:1:10"
1904  call assert_equal('split', &switchbuf)
1905  call writefile(["vim: switchbuf=usetab"], 'Xqftestfile1')
1906  enew | only
1907  set switchbuf=useopen
1908  cexpr "Xqftestfile1:1:10"
1909  call assert_equal('usetab', &switchbuf)
1910  call writefile(["vim: switchbuf&vim"], 'Xqftestfile1')
1911  enew | only
1912  set switchbuf=useopen
1913  cexpr "Xqftestfile1:1:10"
1914  call assert_equal('', &switchbuf)
1915
1916  call delete('Xqftestfile1')
1917  call delete('Xqftestfile2')
1918  call delete('Xqftestfile3')
1919  set switchbuf&vim
1920
1921  enew | only
1922endfunc
1923
1924func Xadjust_qflnum(cchar)
1925  call s:setup_commands(a:cchar)
1926
1927  enew | only
1928
1929  let fname = 'Xqftestfile' . a:cchar
1930  call s:create_test_file(fname)
1931  exe 'edit ' . fname
1932
1933  Xgetexpr [fname . ':5:Line5',
1934	      \ fname . ':10:Line10',
1935	      \ fname . ':15:Line15',
1936	      \ fname . ':20:Line20']
1937
1938  6,14delete
1939  call append(6, ['Buffer', 'Window'])
1940
1941  let l = g:Xgetlist()
1942  call assert_equal(5, l[0].lnum)
1943  call assert_equal(6, l[2].lnum)
1944  call assert_equal(13, l[3].lnum)
1945
1946  " If a file doesn't have any quickfix entries, then deleting lines in the
1947  " file should not update the quickfix list
1948  call g:Xsetlist([], 'f')
1949  1,2delete
1950  call assert_equal([], g:Xgetlist())
1951
1952  enew!
1953  call delete(fname)
1954endfunc
1955
1956func Test_adjust_lnum()
1957  call setloclist(0, [])
1958  call Xadjust_qflnum('c')
1959  call setqflist([])
1960  call Xadjust_qflnum('l')
1961endfunc
1962
1963" Tests for the :grep/:lgrep and :grepadd/:lgrepadd commands
1964func s:test_xgrep(cchar)
1965  call s:setup_commands(a:cchar)
1966
1967  " The following lines are used for the grep test. Don't remove.
1968  " Grep_Test_Text: Match 1
1969  " Grep_Test_Text: Match 2
1970  " GrepAdd_Test_Text: Match 1
1971  " GrepAdd_Test_Text: Match 2
1972  enew! | only
1973  set makeef&vim
1974  silent Xgrep Grep_Test_Text: test_quickfix.vim
1975  call assert_true(len(g:Xgetlist()) == 5)
1976  Xopen
1977  call assert_true(w:quickfix_title =~ '^:grep')
1978  Xclose
1979  enew
1980  set makeef=Temp_File_##
1981  silent Xgrepadd GrepAdd_Test_Text: test_quickfix.vim
1982  call assert_true(len(g:Xgetlist()) == 9)
1983
1984  " Try with 'grepprg' set to 'internal'
1985  set grepprg=internal
1986  silent Xgrep Grep_Test_Text: test_quickfix.vim
1987  silent Xgrepadd GrepAdd_Test_Text: test_quickfix.vim
1988  call assert_true(len(g:Xgetlist()) == 9)
1989  set grepprg&vim
1990
1991  call writefile(['Vim'], 'XtestTempFile')
1992  set makeef=XtestTempFile
1993  silent Xgrep Grep_Test_Text: test_quickfix.vim
1994  call assert_equal(5, len(g:Xgetlist()))
1995  call assert_false(filereadable('XtestTempFile'))
1996  set makeef&vim
1997endfunc
1998
1999func Test_grep()
2000  " The grepprg may not be set on non-Unix systems
2001  CheckUnix
2002
2003  call s:test_xgrep('c')
2004  call s:test_xgrep('l')
2005endfunc
2006
2007func Test_two_windows()
2008  " Use one 'errorformat' for two windows.  Add an expression to each of them,
2009  " make sure they each keep their own state.
2010  set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f'
2011  call mkdir('Xone/a', 'p')
2012  call mkdir('Xtwo/a', 'p')
2013  let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7']
2014  call writefile(lines, 'Xone/a/one.txt')
2015  call writefile(lines, 'Xtwo/a/two.txt')
2016
2017  new one
2018  let one_id = win_getid()
2019  lexpr ""
2020  new two
2021  let two_id = win_getid()
2022  lexpr ""
2023
2024  laddexpr "Entering dir 'Xtwo/a'"
2025  call win_gotoid(one_id)
2026  laddexpr "Entering dir 'Xone/a'"
2027  call win_gotoid(two_id)
2028  laddexpr 'two.txt:5:two two two'
2029  call win_gotoid(one_id)
2030  laddexpr 'one.txt:3:one one one'
2031
2032  let loc_one = getloclist(one_id)
2033  call assert_equal('Xone/a/one.txt', bufname(loc_one[1].bufnr))
2034  call assert_equal(3, loc_one[1].lnum)
2035
2036  let loc_two = getloclist(two_id)
2037  call assert_equal('Xtwo/a/two.txt', bufname(loc_two[1].bufnr))
2038  call assert_equal(5, loc_two[1].lnum)
2039
2040  call win_gotoid(one_id)
2041  bwipe!
2042  call win_gotoid(two_id)
2043  bwipe!
2044  call delete('Xone', 'rf')
2045  call delete('Xtwo', 'rf')
2046endfunc
2047
2048func XbottomTests(cchar)
2049  call s:setup_commands(a:cchar)
2050
2051  " Calling lbottom without any errors should fail
2052  if a:cchar == 'l'
2053      call assert_fails('lbottom', 'E776:')
2054  endif
2055
2056  call g:Xsetlist([{'filename': 'foo', 'lnum': 42}])
2057  Xopen
2058  let wid = win_getid()
2059  call assert_equal(1, line('.'))
2060  wincmd w
2061  call g:Xsetlist([{'filename': 'var', 'lnum': 24}], 'a')
2062  Xbottom
2063  call win_gotoid(wid)
2064  call assert_equal(2, line('.'))
2065  Xclose
2066endfunc
2067
2068" Tests for the :cbottom and :lbottom commands
2069func Test_cbottom()
2070  call XbottomTests('c')
2071  call XbottomTests('l')
2072endfunc
2073
2074func HistoryTest(cchar)
2075  call s:setup_commands(a:cchar)
2076
2077  " clear all lists after the first one, then replace the first one.
2078  call g:Xsetlist([])
2079  call assert_fails('Xolder 99', 'E380:')
2080  let entry = {'filename': 'foo', 'lnum': 42}
2081  call g:Xsetlist([entry], 'r')
2082  call g:Xsetlist([entry, entry])
2083  call g:Xsetlist([entry, entry, entry])
2084  let res = split(execute(a:cchar . 'hist'), "\n")
2085  call assert_equal(3, len(res))
2086  let common = 'errors     :set' . (a:cchar == 'c' ? 'qf' : 'loc') . 'list()'
2087  call assert_equal('  error list 1 of 3; 1 ' . common, res[0])
2088  call assert_equal('  error list 2 of 3; 2 ' . common, res[1])
2089  call assert_equal('> error list 3 of 3; 3 ' . common, res[2])
2090
2091  " Test for changing the quickfix lists
2092  call assert_equal(3, g:Xgetlist({'nr' : 0}).nr)
2093  exe '1' . a:cchar . 'hist'
2094  call assert_equal(1, g:Xgetlist({'nr' : 0}).nr)
2095  exe '3' . a:cchar . 'hist'
2096  call assert_equal(3, g:Xgetlist({'nr' : 0}).nr)
2097  call assert_fails('-2' . a:cchar . 'hist', 'E16:')
2098  call assert_fails('4' . a:cchar . 'hist', 'E16:')
2099
2100  call g:Xsetlist([], 'f')
2101  let l = split(execute(a:cchar . 'hist'), "\n")
2102  call assert_equal('No entries', l[0])
2103  if a:cchar == 'c'
2104    call assert_fails('4chist', 'E16:')
2105  else
2106    call assert_fails('4lhist', 'E776:')
2107  endif
2108
2109  " An empty list should still show the stack history
2110  call g:Xsetlist([])
2111  let res = split(execute(a:cchar . 'hist'), "\n")
2112  call assert_equal('> error list 1 of 1; 0 ' . common, res[0])
2113
2114  call g:Xsetlist([], 'f')
2115endfunc
2116
2117func Test_history()
2118  call HistoryTest('c')
2119  call HistoryTest('l')
2120endfunc
2121
2122func Test_duplicate_buf()
2123  " make sure we can get the highest buffer number
2124  edit DoesNotExist
2125  edit DoesNotExist2
2126  let last_buffer = bufnr("$")
2127
2128  " make sure only one buffer is created
2129  call writefile(['this one', 'that one'], 'Xgrepthis')
2130  vimgrep one Xgrepthis
2131  vimgrep one Xgrepthis
2132  call assert_equal(last_buffer + 1, bufnr("$"))
2133
2134  call delete('Xgrepthis')
2135endfunc
2136
2137" Quickfix/Location list set/get properties tests
2138func Xproperty_tests(cchar)
2139  call s:setup_commands(a:cchar)
2140
2141  " Error cases
2142  call assert_fails('call g:Xgetlist(99)', 'E715:')
2143  call assert_fails('call g:Xsetlist(99)', 'E714:')
2144  call assert_fails('call g:Xsetlist([], "a", [])', 'E715:')
2145
2146  " Set and get the title
2147  call g:Xsetlist([])
2148  Xopen
2149  wincmd p
2150  call g:Xsetlist([{'filename':'foo', 'lnum':27}])
2151  let s = g:Xsetlist([], 'a', {'title' : 'Sample'})
2152  call assert_equal(0, s)
2153  let d = g:Xgetlist({"title":1})
2154  call assert_equal('Sample', d.title)
2155  " Try setting title to a non-string value
2156  call assert_equal(-1, g:Xsetlist([], 'a', {'title' : ['Test']}))
2157  call assert_equal('Sample', g:Xgetlist({"title":1}).title)
2158
2159  Xopen
2160  call assert_equal('Sample', w:quickfix_title)
2161  Xclose
2162
2163  " Tests for action argument
2164  silent! Xolder 999
2165  let qfnr = g:Xgetlist({'all':1}).nr
2166  call g:Xsetlist([], 'r', {'title' : 'N1'})
2167  call assert_equal('N1', g:Xgetlist({'all':1}).title)
2168  call g:Xsetlist([], ' ', {'title' : 'N2'})
2169  call assert_equal(qfnr + 1, g:Xgetlist({'all':1}).nr)
2170
2171  let res = g:Xgetlist({'nr': 0})
2172  call assert_equal(qfnr + 1, res.nr)
2173  call assert_equal(['nr'], keys(res))
2174
2175  call g:Xsetlist([], ' ', {'title' : 'N3'})
2176  call assert_equal('N2', g:Xgetlist({'nr':2, 'title':1}).title)
2177
2178  " Changing the title of an earlier quickfix list
2179  call g:Xsetlist([], 'r', {'title' : 'NewTitle', 'nr' : 2})
2180  call assert_equal('NewTitle', g:Xgetlist({'nr':2, 'title':1}).title)
2181
2182  " Changing the title of an invalid quickfix list
2183  call assert_equal(-1, g:Xsetlist([], ' ',
2184        \ {'title' : 'SomeTitle', 'nr' : 99}))
2185  call assert_equal(-1, g:Xsetlist([], ' ',
2186        \ {'title' : 'SomeTitle', 'nr' : 'abc'}))
2187
2188  if a:cchar == 'c'
2189    copen
2190    call assert_equal({'winid':win_getid()}, getqflist({'winid':1}))
2191    cclose
2192  endif
2193
2194  " Invalid arguments
2195  call assert_fails('call g:Xgetlist([])', 'E715:')
2196  call assert_fails('call g:Xsetlist([], "a", [])', 'E715:')
2197  let s = g:Xsetlist([], 'a', {'abc':1})
2198  call assert_equal(-1, s)
2199
2200  call assert_equal({}, g:Xgetlist({'abc':1}))
2201  call assert_equal('', g:Xgetlist({'nr':99, 'title':1}).title)
2202  call assert_equal('', g:Xgetlist({'nr':[], 'title':1}).title)
2203
2204  if a:cchar == 'l'
2205    call assert_equal({}, getloclist(99, {'title': 1}))
2206  endif
2207
2208  " Context related tests
2209  let s = g:Xsetlist([], 'a', {'context':[1,2,3]})
2210  call assert_equal(0, s)
2211  call test_garbagecollect_now()
2212  let d = g:Xgetlist({'context':1})
2213  call assert_equal([1,2,3], d.context)
2214  call g:Xsetlist([], 'a', {'context':{'color':'green'}})
2215  let d = g:Xgetlist({'context':1})
2216  call assert_equal({'color':'green'}, d.context)
2217  call g:Xsetlist([], 'a', {'context':"Context info"})
2218  let d = g:Xgetlist({'context':1})
2219  call assert_equal("Context info", d.context)
2220  call g:Xsetlist([], 'a', {'context':246})
2221  let d = g:Xgetlist({'context':1})
2222  call assert_equal(246, d.context)
2223  " set other Vim data types as context
2224  call g:Xsetlist([], 'a', {'context' : test_null_blob()})
2225  if has('channel')
2226    call g:Xsetlist([], 'a', {'context' : test_null_channel()})
2227  endif
2228  if has('job')
2229    call g:Xsetlist([], 'a', {'context' : test_null_job()})
2230  endif
2231  call g:Xsetlist([], 'a', {'context' : test_null_function()})
2232  call g:Xsetlist([], 'a', {'context' : test_null_partial()})
2233  call g:Xsetlist([], 'a', {'context' : ''})
2234  call test_garbagecollect_now()
2235  if a:cchar == 'l'
2236    " Test for copying context across two different location lists
2237    new | only
2238    let w1_id = win_getid()
2239    let l = [1]
2240    call setloclist(0, [], 'a', {'context':l})
2241    new
2242    let w2_id = win_getid()
2243    call add(l, 2)
2244    call assert_equal([1, 2], getloclist(w1_id, {'context':1}).context)
2245    call assert_equal([1, 2], getloclist(w2_id, {'context':1}).context)
2246    unlet! l
2247    call assert_equal([1, 2], getloclist(w2_id, {'context':1}).context)
2248    only
2249    call setloclist(0, [], 'f')
2250    call assert_equal('', getloclist(0, {'context':1}).context)
2251  endif
2252
2253  " Test for changing the context of previous quickfix lists
2254  call g:Xsetlist([], 'f')
2255  Xexpr "One"
2256  Xexpr "Two"
2257  Xexpr "Three"
2258  call g:Xsetlist([], 'r', {'context' : [1], 'nr' : 1})
2259  call g:Xsetlist([], 'a', {'context' : [2], 'nr' : 2})
2260  " Also, check for setting the context using quickfix list number zero.
2261  call g:Xsetlist([], 'r', {'context' : [3], 'nr' : 0})
2262  call test_garbagecollect_now()
2263  let l = g:Xgetlist({'nr' : 1, 'context' : 1})
2264  call assert_equal([1], l.context)
2265  let l = g:Xgetlist({'nr' : 2, 'context' : 1})
2266  call assert_equal([2], l.context)
2267  let l = g:Xgetlist({'nr' : 3, 'context' : 1})
2268  call assert_equal([3], l.context)
2269
2270  " Test for changing the context through reference and for garbage
2271  " collection of quickfix context
2272  let l = ["red"]
2273  call g:Xsetlist([], ' ', {'context' : l})
2274  call add(l, "blue")
2275  let x = g:Xgetlist({'context' : 1})
2276  call add(x.context, "green")
2277  call assert_equal(["red", "blue", "green"], l)
2278  call assert_equal(["red", "blue", "green"], x.context)
2279  unlet l
2280  call test_garbagecollect_now()
2281  let m = g:Xgetlist({'context' : 1})
2282  call assert_equal(["red", "blue", "green"], m.context)
2283
2284  " Test for setting/getting items
2285  Xexpr ""
2286  let qfprev = g:Xgetlist({'nr':0})
2287  let s = g:Xsetlist([], ' ', {'title':'Green',
2288        \ 'items' : [{'filename':'F1', 'lnum':10}]})
2289  call assert_equal(0, s)
2290  let qfcur = g:Xgetlist({'nr':0})
2291  call assert_true(qfcur.nr == qfprev.nr + 1)
2292  let l = g:Xgetlist({'items':1})
2293  call assert_equal('F1', bufname(l.items[0].bufnr))
2294  call assert_equal(10, l.items[0].lnum)
2295  call g:Xsetlist([], 'a', {'items' : [{'filename':'F2', 'lnum':20},
2296        \  {'filename':'F2', 'lnum':30}]})
2297  let l = g:Xgetlist({'items':1})
2298  call assert_equal('F2', bufname(l.items[2].bufnr))
2299  call assert_equal(30, l.items[2].lnum)
2300  call g:Xsetlist([], 'r', {'items' : [{'filename':'F3', 'lnum':40}]})
2301  let l = g:Xgetlist({'items':1})
2302  call assert_equal('F3', bufname(l.items[0].bufnr))
2303  call assert_equal(40, l.items[0].lnum)
2304  call g:Xsetlist([], 'r', {'items' : []})
2305  let l = g:Xgetlist({'items':1})
2306  call assert_equal(0, len(l.items))
2307
2308  call g:Xsetlist([], 'r', {'title' : 'TestTitle'})
2309  call g:Xsetlist([], 'r', {'items' : [{'filename' : 'F1', 'lnum' : 10, 'text' : 'L10'}]})
2310  call g:Xsetlist([], 'r', {'items' : [{'filename' : 'F1', 'lnum' : 10, 'text' : 'L10'}]})
2311  call assert_equal('TestTitle', g:Xgetlist({'title' : 1}).title)
2312
2313  " Test for getting id of window associated with a location list window
2314  if a:cchar == 'l'
2315    only
2316    call assert_equal(0, g:Xgetlist({'all' : 1}).filewinid)
2317    let wid = win_getid()
2318    Xopen
2319    call assert_equal(wid, g:Xgetlist({'filewinid' : 1}).filewinid)
2320    wincmd w
2321    call assert_equal(0, g:Xgetlist({'filewinid' : 1}).filewinid)
2322    only
2323  endif
2324
2325  " The following used to crash Vim with address sanitizer
2326  call g:Xsetlist([], 'f')
2327  call g:Xsetlist([], 'a', {'items' : [{'filename':'F1', 'lnum':10}]})
2328  call assert_equal(10, g:Xgetlist({'items':1}).items[0].lnum)
2329
2330  " Try setting the items using a string
2331  call assert_equal(-1, g:Xsetlist([], ' ', {'items' : 'Test'}))
2332
2333  " Save and restore the quickfix stack
2334  call g:Xsetlist([], 'f')
2335  call assert_equal(0, g:Xgetlist({'nr':'$'}).nr)
2336  Xexpr "File1:10:Line1"
2337  Xexpr "File2:20:Line2"
2338  Xexpr "File3:30:Line3"
2339  let last_qf = g:Xgetlist({'nr':'$'}).nr
2340  call assert_equal(3, last_qf)
2341  let qstack = []
2342  for i in range(1, last_qf)
2343    let qstack = add(qstack, g:Xgetlist({'nr':i, 'all':1}))
2344  endfor
2345  call g:Xsetlist([], 'f')
2346  for i in range(len(qstack))
2347    call g:Xsetlist([], ' ', qstack[i])
2348  endfor
2349  call assert_equal(3, g:Xgetlist({'nr':'$'}).nr)
2350  call assert_equal(10, g:Xgetlist({'nr':1, 'items':1}).items[0].lnum)
2351  call assert_equal(20, g:Xgetlist({'nr':2, 'items':1}).items[0].lnum)
2352  call assert_equal(30, g:Xgetlist({'nr':3, 'items':1}).items[0].lnum)
2353  call g:Xsetlist([], 'f')
2354
2355  " Swap two quickfix lists
2356  Xexpr "File1:10:Line10"
2357  Xexpr "File2:20:Line20"
2358  Xexpr "File3:30:Line30"
2359  call g:Xsetlist([], 'r', {'nr':1,'title':'Colors','context':['Colors']})
2360  call g:Xsetlist([], 'r', {'nr':2,'title':'Fruits','context':['Fruits']})
2361  let l1=g:Xgetlist({'nr':1,'all':1})
2362  let l2=g:Xgetlist({'nr':2,'all':1})
2363  let save_id = l1.id
2364  let l1.id=l2.id
2365  let l2.id=save_id
2366  call g:Xsetlist([], 'r', l1)
2367  call g:Xsetlist([], 'r', l2)
2368  let newl1=g:Xgetlist({'nr':1,'all':1})
2369  let newl2=g:Xgetlist({'nr':2,'all':1})
2370  call assert_equal('Fruits', newl1.title)
2371  call assert_equal(['Fruits'], newl1.context)
2372  call assert_equal('Line20', newl1.items[0].text)
2373  call assert_equal('Colors', newl2.title)
2374  call assert_equal(['Colors'], newl2.context)
2375  call assert_equal('Line10', newl2.items[0].text)
2376  call g:Xsetlist([], 'f')
2377
2378  " Cannot specify both a non-empty list argument and a dict argument
2379  call assert_fails("call g:Xsetlist([{}], ' ', {})", 'E475:')
2380endfunc
2381
2382func Test_qf_property()
2383  call Xproperty_tests('c')
2384  call Xproperty_tests('l')
2385endfunc
2386
2387" Test for setting the current index in the location/quickfix list
2388func Xtest_setqfidx(cchar)
2389  call s:setup_commands(a:cchar)
2390
2391  Xgetexpr "F1:10:1:Line1\nF2:20:2:Line2\nF3:30:3:Line3"
2392  Xgetexpr "F4:10:1:Line1\nF5:20:2:Line2\nF6:30:3:Line3"
2393  Xgetexpr "F7:10:1:Line1\nF8:20:2:Line2\nF9:30:3:Line3"
2394
2395  call g:Xsetlist([], 'a', {'nr' : 3, 'idx' : 2})
2396  call g:Xsetlist([], 'a', {'nr' : 2, 'idx' : 2})
2397  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 3})
2398  Xolder 2
2399  Xopen
2400  call assert_equal(3, line('.'))
2401  Xnewer
2402  call assert_equal(2, line('.'))
2403  Xnewer
2404  call assert_equal(2, line('.'))
2405  " Update the current index with the quickfix window open
2406  wincmd w
2407  call g:Xsetlist([], 'a', {'nr' : 3, 'idx' : 3})
2408  Xopen
2409  call assert_equal(3, line('.'))
2410  Xclose
2411
2412  " Set the current index to the last entry
2413  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : '$'})
2414  call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx)
2415  " A large value should set the index to the last index
2416  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 1})
2417  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 999})
2418  call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx)
2419  " Invalid index values
2420  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : -1})
2421  call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx)
2422  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 0})
2423  call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx)
2424  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 'xx'})
2425  call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx)
2426  call assert_fails("call g:Xsetlist([], 'a', {'nr':1, 'idx':[]})", 'E745:')
2427
2428  call g:Xsetlist([], 'f')
2429  new | only
2430endfunc
2431
2432func Test_setqfidx()
2433  call Xtest_setqfidx('c')
2434  call Xtest_setqfidx('l')
2435endfunc
2436
2437" Tests for the QuickFixCmdPre/QuickFixCmdPost autocommands
2438func QfAutoCmdHandler(loc, cmd)
2439  call add(g:acmds, a:loc . a:cmd)
2440endfunc
2441
2442func Test_Autocmd()
2443  autocmd QuickFixCmdPre * call QfAutoCmdHandler('pre', expand('<amatch>'))
2444  autocmd QuickFixCmdPost * call QfAutoCmdHandler('post', expand('<amatch>'))
2445
2446  let g:acmds = []
2447  cexpr "F1:10:Line 10"
2448  caddexpr "F1:20:Line 20"
2449  cgetexpr "F1:30:Line 30"
2450  cexpr ""
2451  caddexpr ""
2452  cgetexpr ""
2453  silent! cexpr non_existing_func()
2454  silent! caddexpr non_existing_func()
2455  silent! cgetexpr non_existing_func()
2456  let l = ['precexpr',
2457	      \ 'postcexpr',
2458	      \ 'precaddexpr',
2459	      \ 'postcaddexpr',
2460	      \ 'precgetexpr',
2461	      \ 'postcgetexpr',
2462	      \ 'precexpr',
2463	      \ 'postcexpr',
2464	      \ 'precaddexpr',
2465	      \ 'postcaddexpr',
2466	      \ 'precgetexpr',
2467	      \ 'postcgetexpr',
2468	      \ 'precexpr',
2469	      \ 'precaddexpr',
2470	      \ 'precgetexpr']
2471  call assert_equal(l, g:acmds)
2472
2473  let g:acmds = []
2474  enew! | call append(0, "F2:10:Line 10")
2475  cbuffer!
2476  enew! | call append(0, "F2:20:Line 20")
2477  cgetbuffer
2478  enew! | call append(0, "F2:30:Line 30")
2479  caddbuffer
2480  new
2481  let bnum = bufnr('%')
2482  bunload
2483  exe 'silent! cbuffer! ' . bnum
2484  exe 'silent! cgetbuffer ' . bnum
2485  exe 'silent! caddbuffer ' . bnum
2486  enew!
2487  let l = ['precbuffer',
2488	      \ 'postcbuffer',
2489	      \ 'precgetbuffer',
2490	      \ 'postcgetbuffer',
2491	      \ 'precaddbuffer',
2492	      \ 'postcaddbuffer',
2493	      \ 'precbuffer',
2494	      \ 'precgetbuffer',
2495	      \ 'precaddbuffer']
2496  call assert_equal(l, g:acmds)
2497
2498  call writefile(['Xtest:1:Line1'], 'Xtest')
2499  call writefile([], 'Xempty')
2500  let g:acmds = []
2501  cfile Xtest
2502  caddfile Xtest
2503  cgetfile Xtest
2504  cfile Xempty
2505  caddfile Xempty
2506  cgetfile Xempty
2507  silent! cfile do_not_exist
2508  silent! caddfile do_not_exist
2509  silent! cgetfile do_not_exist
2510  let l = ['precfile',
2511	      \ 'postcfile',
2512	      \ 'precaddfile',
2513	      \ 'postcaddfile',
2514	      \ 'precgetfile',
2515	      \ 'postcgetfile',
2516	      \ 'precfile',
2517	      \ 'postcfile',
2518	      \ 'precaddfile',
2519	      \ 'postcaddfile',
2520	      \ 'precgetfile',
2521	      \ 'postcgetfile',
2522	      \ 'precfile',
2523	      \ 'postcfile',
2524	      \ 'precaddfile',
2525	      \ 'postcaddfile',
2526	      \ 'precgetfile',
2527	      \ 'postcgetfile']
2528  call assert_equal(l, g:acmds)
2529
2530  let g:acmds = []
2531  helpgrep quickfix
2532  silent! helpgrep non_existing_help_topic
2533  vimgrep test Xtest
2534  vimgrepadd test Xtest
2535  silent! vimgrep non_existing_test Xtest
2536  silent! vimgrepadd non_existing_test Xtest
2537  set makeprg=
2538  silent! make
2539  set makeprg&
2540  let l = ['prehelpgrep',
2541	      \ 'posthelpgrep',
2542	      \ 'prehelpgrep',
2543	      \ 'posthelpgrep',
2544	      \ 'previmgrep',
2545	      \ 'postvimgrep',
2546	      \ 'previmgrepadd',
2547	      \ 'postvimgrepadd',
2548	      \ 'previmgrep',
2549	      \ 'postvimgrep',
2550	      \ 'previmgrepadd',
2551	      \ 'postvimgrepadd',
2552	      \ 'premake',
2553	      \ 'postmake']
2554  call assert_equal(l, g:acmds)
2555
2556  if has('unix')
2557    " Run this test only on Unix-like systems. The grepprg may not be set on
2558    " non-Unix systems.
2559    " The following lines are used for the grep test. Don't remove.
2560    " Grep_Autocmd_Text: Match 1
2561    " GrepAdd_Autocmd_Text: Match 2
2562    let g:acmds = []
2563    silent grep Grep_Autocmd_Text test_quickfix.vim
2564    silent grepadd GrepAdd_Autocmd_Text test_quickfix.vim
2565    silent grep abc123def Xtest
2566    silent grepadd abc123def Xtest
2567    set grepprg=internal
2568    silent grep Grep_Autocmd_Text test_quickfix.vim
2569    silent grepadd GrepAdd_Autocmd_Text test_quickfix.vim
2570    silent lgrep Grep_Autocmd_Text test_quickfix.vim
2571    silent lgrepadd GrepAdd_Autocmd_Text test_quickfix.vim
2572    set grepprg&vim
2573    let l = ['pregrep',
2574		\ 'postgrep',
2575		\ 'pregrepadd',
2576		\ 'postgrepadd',
2577		\ 'pregrep',
2578		\ 'postgrep',
2579		\ 'pregrepadd',
2580		\ 'postgrepadd',
2581		\ 'pregrep',
2582		\ 'postgrep',
2583		\ 'pregrepadd',
2584		\ 'postgrepadd',
2585		\ 'prelgrep',
2586		\ 'postlgrep',
2587		\ 'prelgrepadd',
2588		\ 'postlgrepadd']
2589    call assert_equal(l, g:acmds)
2590  endif
2591
2592  call delete('Xtest')
2593  call delete('Xempty')
2594  au! QuickFixCmdPre
2595  au! QuickFixCmdPost
2596endfunc
2597
2598func Test_Autocmd_Exception()
2599  set efm=%m
2600  lgetexpr '?'
2601
2602  try
2603    call DoesNotExit()
2604  catch
2605    lgetexpr '1'
2606  finally
2607    lgetexpr '1'
2608  endtry
2609
2610  call assert_equal('1', getloclist(0)[0].text)
2611
2612  set efm&vim
2613endfunc
2614
2615func Test_caddbuffer_wrong()
2616  " This used to cause a memory access in freed memory.
2617  let save_efm = &efm
2618  set efm=%EEEE%m,%WWWW,%+CCCC%>%#,%GGGG%.#
2619  cgetexpr ['WWWW', 'EEEE', 'CCCC']
2620  let &efm = save_efm
2621  caddbuffer
2622  bwipe!
2623endfunc
2624
2625func Test_caddexpr_wrong()
2626  " This used to cause a memory access in freed memory.
2627  cbuffer
2628  cbuffer
2629  copen
2630  let save_efm = &efm
2631  set efm=%
2632  call assert_fails('caddexpr ""', 'E376:')
2633  let &efm = save_efm
2634endfunc
2635
2636func Test_dirstack_cleanup()
2637  " This used to cause a memory access in freed memory.
2638  let save_efm = &efm
2639  lexpr '0'
2640  lopen
2641  fun X(c)
2642    let save_efm=&efm
2643    set efm=%D%f
2644    if a:c == 'c'
2645      caddexpr '::'
2646    else
2647      laddexpr ':0:0'
2648    endif
2649    let &efm=save_efm
2650  endfun
2651  call X('c')
2652  call X('l')
2653  call setqflist([], 'r')
2654  caddbuffer
2655  let &efm = save_efm
2656endfunc
2657
2658" Tests for jumping to entries from the location list window and quickfix
2659" window
2660func Test_cwindow_jump()
2661  set efm=%f%%%l%%%m
2662  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2663  lopen | only
2664  lfirst
2665  call assert_true(winnr('$') == 2)
2666  call assert_true(winnr() == 1)
2667  " Location list for the new window should be set
2668  call assert_true(getloclist(0)[2].text == 'Line 30')
2669
2670  " Open a scratch buffer
2671  " Open a new window and create a location list
2672  " Open the location list window and close the other window
2673  " Jump to an entry.
2674  " Should create a new window and jump to the entry. The scratch buffer
2675  " should not be used.
2676  enew | only
2677  set buftype=nofile
2678  below new
2679  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2680  lopen
2681  2wincmd c
2682  lnext
2683  call assert_true(winnr('$') == 3)
2684  call assert_true(winnr() == 2)
2685
2686  " Open two windows with two different location lists
2687  " Open the location list window and close the previous window
2688  " Jump to an entry in the location list window
2689  " Should open the file in the first window and not set the location list.
2690  enew | only
2691  lgetexpr ["F1%5%Line 5"]
2692  below new
2693  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2694  lopen
2695  2wincmd c
2696  lnext
2697  call assert_true(winnr() == 1)
2698  call assert_true(getloclist(0)[0].text == 'Line 5')
2699
2700  enew | only
2701  cgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2702  copen
2703  cnext
2704  call assert_true(winnr('$') == 2)
2705  call assert_true(winnr() == 1)
2706
2707  " open the quickfix buffer in two windows and jump to an entry. Should open
2708  " the file in the first quickfix window.
2709  enew | only
2710  copen
2711  let bnum = bufnr('')
2712  exe 'sbuffer ' . bnum
2713  wincmd b
2714  cfirst
2715  call assert_equal(2, winnr())
2716  call assert_equal('F1', @%)
2717  enew | only
2718  exe 'sb' bnum
2719  exe 'botright sb' bnum
2720  wincmd t
2721  clast
2722  call assert_equal(2, winnr())
2723  call assert_equal('quickfix', getwinvar(1, '&buftype'))
2724  call assert_equal('quickfix', getwinvar(3, '&buftype'))
2725
2726  " Jumping to a file from the location list window should find a usable
2727  " window by wrapping around the window list.
2728  enew | only
2729  call setloclist(0, [], 'f')
2730  new | new
2731  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2732  lopen
2733  1close
2734  call assert_equal(0, getloclist(3, {'id' : 0}).id)
2735  lnext
2736  call assert_equal(3, winnr())
2737  call assert_equal(getloclist(1, {'id' : 0}).id, getloclist(3, {'id' : 0}).id)
2738
2739  enew | only
2740  set efm&vim
2741endfunc
2742
2743func Test_cwindow_highlight()
2744  CheckScreendump
2745
2746  let lines =<< trim END
2747	call setline(1, ['some', 'text', 'with', 'matches'])
2748	write XCwindow
2749	vimgrep e XCwindow
2750	redraw
2751	cwindow 4
2752  END
2753  call writefile(lines, 'XtestCwindow')
2754  let buf = RunVimInTerminal('-S XtestCwindow', #{rows: 12})
2755  call VerifyScreenDump(buf, 'Test_quickfix_cwindow_1', {})
2756
2757  call term_sendkeys(buf, ":cnext\<CR>")
2758  call VerifyScreenDump(buf, 'Test_quickfix_cwindow_2', {})
2759
2760  " clean up
2761  call StopVimInTerminal(buf)
2762  call delete('XtestCwindow')
2763  call delete('XCwindow')
2764endfunc
2765
2766func XvimgrepTests(cchar)
2767  call s:setup_commands(a:cchar)
2768
2769  call writefile(['Editor:VIM vim',
2770	      \ 'Editor:Emacs EmAcS',
2771	      \ 'Editor:Notepad NOTEPAD'], 'Xtestfile1')
2772  call writefile(['Linux', 'MacOS', 'MS-Windows'], 'Xtestfile2')
2773
2774  " Error cases
2775  call assert_fails('Xvimgrep /abc *', 'E682:')
2776
2777  let @/=''
2778  call assert_fails('Xvimgrep // *', 'E35:')
2779
2780  call assert_fails('Xvimgrep abc', 'E683:')
2781  call assert_fails('Xvimgrep a1b2c3 Xtestfile1', 'E480:')
2782  call assert_fails('Xvimgrep pat Xa1b2c3', 'E480:')
2783
2784  Xexpr ""
2785  Xvimgrepadd Notepad Xtestfile1
2786  Xvimgrepadd MacOS Xtestfile2
2787  let l = g:Xgetlist()
2788  call assert_equal(2, len(l))
2789  call assert_equal('Editor:Notepad NOTEPAD', l[0].text)
2790
2791  10Xvimgrep #\cvim#g Xtestfile?
2792  let l = g:Xgetlist()
2793  call assert_equal(2, len(l))
2794  call assert_equal(8, l[0].col)
2795  call assert_equal(12, l[1].col)
2796
2797  1Xvimgrep ?Editor? Xtestfile*
2798  let l = g:Xgetlist()
2799  call assert_equal(1, len(l))
2800  call assert_equal('Editor:VIM vim', l[0].text)
2801
2802  edit +3 Xtestfile2
2803  Xvimgrep +\cemacs+j Xtestfile1
2804  let l = g:Xgetlist()
2805  call assert_equal('Xtestfile2', @%)
2806  call assert_equal('Editor:Emacs EmAcS', l[0].text)
2807
2808  " Test for unloading a buffer after vimgrep searched the buffer
2809  %bwipe
2810  Xvimgrep /Editor/j Xtestfile*
2811  call assert_equal(0, getbufinfo('Xtestfile1')[0].loaded)
2812  call assert_equal([], getbufinfo('Xtestfile2'))
2813
2814  call delete('Xtestfile1')
2815  call delete('Xtestfile2')
2816endfunc
2817
2818" Tests for the :vimgrep command
2819func Test_vimgrep()
2820  call XvimgrepTests('c')
2821  call XvimgrepTests('l')
2822endfunc
2823
2824" Test for incsearch highlighting of the :vimgrep pattern
2825" This test used to cause "E315: ml_get: invalid lnum" errors.
2826func Test_vimgrep_incsearch()
2827  enew
2828  set incsearch
2829  call test_override("char_avail", 1)
2830
2831  call feedkeys(":2vimgrep assert test_quickfix.vim test_cdo.vim\<CR>", "ntx")
2832  let l = getqflist()
2833  call assert_equal(2, len(l))
2834
2835  call test_override("ALL", 0)
2836  set noincsearch
2837endfunc
2838
2839" Test vimgrep with the last search pattern not set
2840func Test_vimgrep_with_no_last_search_pat()
2841  let lines =<< trim [SCRIPT]
2842    call assert_fails('vimgrep // *', 'E35:')
2843    call writefile(v:errors, 'Xresult')
2844    qall!
2845  [SCRIPT]
2846  call writefile(lines, 'Xscript')
2847  if RunVim([], [], '--clean -S Xscript')
2848    call assert_equal([], readfile('Xresult'))
2849  endif
2850  call delete('Xscript')
2851  call delete('Xresult')
2852endfunc
2853
2854" Test vimgrep without swap file
2855func Test_vimgrep_without_swap_file()
2856  let lines =<< trim [SCRIPT]
2857    vimgrep grep test_c*
2858    call writefile(['done'], 'Xresult')
2859    qall!
2860  [SCRIPT]
2861  call writefile(lines, 'Xscript')
2862  if RunVim([], [], '--clean -n -S Xscript Xscript')
2863    call assert_equal(['done'], readfile('Xresult'))
2864  endif
2865  call delete('Xscript')
2866  call delete('Xresult')
2867endfunc
2868
2869func Test_vimgrep_existing_swapfile()
2870  call writefile(['match apple with apple'], 'Xapple')
2871  call writefile(['swapfile'], '.Xapple.swp')
2872  let g:foundSwap = 0
2873  let g:ignoreSwapExists = 1
2874  augroup grep
2875    au SwapExists * let foundSwap = 1 | let v:swapchoice = 'e'
2876  augroup END
2877  vimgrep apple Xapple
2878  call assert_equal(1, g:foundSwap)
2879  call assert_match('.Xapple.swo', swapname(''))
2880
2881  call delete('Xapple')
2882  call delete('.Xapple.swp')
2883  augroup grep
2884    au! SwapExists
2885  augroup END
2886  unlet g:ignoreSwapExists
2887endfunc
2888
2889func XfreeTests(cchar)
2890  call s:setup_commands(a:cchar)
2891
2892  enew | only
2893
2894  " Deleting the quickfix stack should work even When the current list is
2895  " somewhere in the middle of the stack
2896  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2897  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2898  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2899  Xolder
2900  call g:Xsetlist([], 'f')
2901  call assert_equal(0, len(g:Xgetlist()))
2902
2903  " After deleting the stack, adding a new list should create a stack with a
2904  " single list.
2905  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2906  call assert_equal(1, g:Xgetlist({'all':1}).nr)
2907
2908  " Deleting the stack from a quickfix window should update/clear the
2909  " quickfix/location list window.
2910  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2911  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2912  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2913  Xolder
2914  Xwindow
2915  call g:Xsetlist([], 'f')
2916  call assert_equal(2, winnr('$'))
2917  call assert_equal(1, line('$'))
2918  Xclose
2919
2920  " Deleting the stack from a non-quickfix window should update/clear the
2921  " quickfix/location list window.
2922  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2923  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2924  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2925  Xolder
2926  Xwindow
2927  wincmd p
2928  call g:Xsetlist([], 'f')
2929  call assert_equal(0, len(g:Xgetlist()))
2930  wincmd p
2931  call assert_equal(2, winnr('$'))
2932  call assert_equal(1, line('$'))
2933
2934  " After deleting the location list stack, if the location list window is
2935  " opened, then a new location list should be created. So opening the
2936  " location list window again should not create a new window.
2937  if a:cchar == 'l'
2938      lexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2939      wincmd p
2940      lopen
2941      call assert_equal(2, winnr('$'))
2942  endif
2943  Xclose
2944endfunc
2945
2946" Tests for the quickfix free functionality
2947func Test_qf_free()
2948  call XfreeTests('c')
2949  call XfreeTests('l')
2950endfunc
2951
2952" Test for buffer overflow when parsing lines and adding new entries to
2953" the quickfix list.
2954func Test_bufoverflow()
2955  set efm=%f:%l:%m
2956  cgetexpr ['File1:100:' . repeat('x', 1025)]
2957
2958  set efm=%+GCompiler:\ %.%#,%f:%l:%m
2959  cgetexpr ['Compiler: ' . repeat('a', 1015), 'File1:10:Hello World']
2960
2961  set efm=%DEntering\ directory\ %f,%f:%l:%m
2962  cgetexpr ['Entering directory ' . repeat('a', 1006),
2963	      \ 'File1:10:Hello World']
2964  set efm&vim
2965endfunc
2966
2967" Tests for getting the quickfix stack size
2968func XsizeTests(cchar)
2969  call s:setup_commands(a:cchar)
2970
2971  call g:Xsetlist([], 'f')
2972  call assert_equal(0, g:Xgetlist({'nr':'$'}).nr)
2973  call assert_equal('', g:Xgetlist({'nr':'$', 'all':1}).title)
2974  call assert_equal(0, g:Xgetlist({'nr':0}).nr)
2975
2976  Xexpr "File1:10:Line1"
2977  Xexpr "File2:20:Line2"
2978  Xexpr "File3:30:Line3"
2979  Xolder | Xolder
2980  call assert_equal(3, g:Xgetlist({'nr':'$'}).nr)
2981  call g:Xsetlist([], 'f')
2982
2983  Xexpr "File1:10:Line1"
2984  Xexpr "File2:20:Line2"
2985  Xexpr "File3:30:Line3"
2986  Xolder | Xolder
2987  call g:Xsetlist([], 'a', {'nr':'$', 'title':'Compiler'})
2988  call assert_equal('Compiler', g:Xgetlist({'nr':3, 'all':1}).title)
2989endfunc
2990
2991func Test_Qf_Size()
2992  call XsizeTests('c')
2993  call XsizeTests('l')
2994endfunc
2995
2996func Test_cclose_from_copen()
2997    augroup QF_Test
2998	au!
2999        au FileType qf :call assert_fails(':cclose', 'E788:')
3000    augroup END
3001    copen
3002    augroup QF_Test
3003	au!
3004    augroup END
3005    augroup! QF_Test
3006endfunc
3007
3008func Test_cclose_in_autocmd()
3009  " Problem is only triggered if "starting" is zero, so that the OptionsSet
3010  " event will be triggered.
3011  call test_override('starting', 1)
3012  augroup QF_Test
3013    au!
3014    au FileType qf :call assert_fails(':cclose', 'E788:')
3015  augroup END
3016  copen
3017  augroup QF_Test
3018    au!
3019  augroup END
3020  augroup! QF_Test
3021  call test_override('starting', 0)
3022endfunc
3023
3024" Check that ":file" without an argument is possible even when "curbuf_lock"
3025" is set.
3026func Test_file_from_copen()
3027  " Works without argument.
3028  augroup QF_Test
3029    au!
3030    au FileType qf file
3031  augroup END
3032  copen
3033
3034  augroup QF_Test
3035    au!
3036  augroup END
3037  cclose
3038
3039  " Fails with argument.
3040  augroup QF_Test
3041    au!
3042    au FileType qf call assert_fails(':file foo', 'E788:')
3043  augroup END
3044  copen
3045  augroup QF_Test
3046    au!
3047  augroup END
3048  cclose
3049
3050  augroup! QF_Test
3051endfunc
3052
3053func Test_resize_from_copen()
3054  augroup QF_Test
3055    au!
3056    au FileType qf resize 5
3057  augroup END
3058  try
3059    " This should succeed without any exception.  No other buffers are
3060    " involved in the autocmd.
3061    copen
3062  finally
3063    augroup QF_Test
3064      au!
3065    augroup END
3066    augroup! QF_Test
3067  endtry
3068endfunc
3069
3070" Tests for the quickfix buffer b:changedtick variable
3071func Xchangedtick_tests(cchar)
3072  call s:setup_commands(a:cchar)
3073
3074  new | only
3075
3076  Xexpr "" | Xexpr "" | Xexpr ""
3077
3078  Xopen
3079  Xolder
3080  Xolder
3081  Xaddexpr "F1:10:Line10"
3082  Xaddexpr "F2:20:Line20"
3083  call g:Xsetlist([{"filename":"F3", "lnum":30, "text":"Line30"}], 'a')
3084  call g:Xsetlist([], 'f')
3085  call assert_equal(8, getbufvar('%', 'changedtick'))
3086  Xclose
3087endfunc
3088
3089func Test_changedtick()
3090  call Xchangedtick_tests('c')
3091  call Xchangedtick_tests('l')
3092endfunc
3093
3094" Tests for parsing an expression using setqflist()
3095func Xsetexpr_tests(cchar)
3096  call s:setup_commands(a:cchar)
3097
3098  let t = ["File1:10:Line10", "File1:20:Line20"]
3099  call g:Xsetlist([], ' ', {'lines' : t})
3100  call g:Xsetlist([], 'a', {'lines' : ["File1:30:Line30"]})
3101
3102  let l = g:Xgetlist()
3103  call assert_equal(3, len(l))
3104  call assert_equal(20, l[1].lnum)
3105  call assert_equal('Line30', l[2].text)
3106  call g:Xsetlist([], 'r', {'lines' : ["File2:5:Line5"]})
3107  let l = g:Xgetlist()
3108  call assert_equal(1, len(l))
3109  call assert_equal('Line5', l[0].text)
3110  call assert_equal(-1, g:Xsetlist([], 'a', {'lines' : 10}))
3111  call assert_equal(-1, g:Xsetlist([], 'a', {'lines' : "F1:10:L10"}))
3112
3113  call g:Xsetlist([], 'f')
3114  " Add entries to multiple lists
3115  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["File1:10:Line10"]})
3116  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["File2:20:Line20"]})
3117  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["File1:15:Line15"]})
3118  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["File2:25:Line25"]})
3119  call assert_equal('Line15', g:Xgetlist({'nr':1, 'items':1}).items[1].text)
3120  call assert_equal('Line25', g:Xgetlist({'nr':2, 'items':1}).items[1].text)
3121
3122  " Adding entries using a custom efm
3123  set efm&
3124  call g:Xsetlist([], ' ', {'efm' : '%f#%l#%m',
3125				\ 'lines' : ["F1#10#L10", "F2#20#L20"]})
3126  call assert_equal(20, g:Xgetlist({'items':1}).items[1].lnum)
3127  call g:Xsetlist([], 'a', {'efm' : '%f#%l#%m', 'lines' : ["F3:30:L30"]})
3128  call assert_equal('F3:30:L30', g:Xgetlist({'items':1}).items[2].text)
3129  call assert_equal(20, g:Xgetlist({'items':1}).items[1].lnum)
3130  call assert_equal(-1, g:Xsetlist([], 'a', {'efm' : [],
3131				\ 'lines' : ['F1:10:L10']}))
3132endfunc
3133
3134func Test_setexpr()
3135  call Xsetexpr_tests('c')
3136  call Xsetexpr_tests('l')
3137endfunc
3138
3139" Tests for per quickfix/location list directory stack
3140func Xmultidirstack_tests(cchar)
3141  call s:setup_commands(a:cchar)
3142
3143  call g:Xsetlist([], 'f')
3144  Xexpr "" | Xexpr ""
3145
3146  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["Entering dir 'Xone/a'"]})
3147  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["Entering dir 'Xtwo/a'"]})
3148  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["one.txt:3:one one one"]})
3149  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["two.txt:5:two two two"]})
3150
3151  let l1 = g:Xgetlist({'nr':1, 'items':1})
3152  let l2 = g:Xgetlist({'nr':2, 'items':1})
3153  call assert_equal('Xone/a/one.txt', bufname(l1.items[1].bufnr))
3154  call assert_equal(3, l1.items[1].lnum)
3155  call assert_equal('Xtwo/a/two.txt', bufname(l2.items[1].bufnr))
3156  call assert_equal(5, l2.items[1].lnum)
3157endfunc
3158
3159func Test_multidirstack()
3160  call mkdir('Xone/a', 'p')
3161  call mkdir('Xtwo/a', 'p')
3162  let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7']
3163  call writefile(lines, 'Xone/a/one.txt')
3164  call writefile(lines, 'Xtwo/a/two.txt')
3165  let save_efm = &efm
3166  set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f'
3167
3168  call Xmultidirstack_tests('c')
3169  call Xmultidirstack_tests('l')
3170
3171  let &efm = save_efm
3172  call delete('Xone', 'rf')
3173  call delete('Xtwo', 'rf')
3174endfunc
3175
3176" Tests for per quickfix/location list file stack
3177func Xmultifilestack_tests(cchar)
3178  call s:setup_commands(a:cchar)
3179
3180  call g:Xsetlist([], 'f')
3181  Xexpr "" | Xexpr ""
3182
3183  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["[one.txt]"]})
3184  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["[two.txt]"]})
3185  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["(3,5) one one one"]})
3186  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["(5,9) two two two"]})
3187
3188  let l1 = g:Xgetlist({'nr':1, 'items':1})
3189  let l2 = g:Xgetlist({'nr':2, 'items':1})
3190  call assert_equal('one.txt', bufname(l1.items[1].bufnr))
3191  call assert_equal(3, l1.items[1].lnum)
3192  call assert_equal('two.txt', bufname(l2.items[1].bufnr))
3193  call assert_equal(5, l2.items[1].lnum)
3194
3195  " Test for start of a new error line in the same line where a previous
3196  " error line ends with a file stack.
3197  let efm_val = 'Error\ l%l\ in\ %f,'
3198  let efm_val .= '%-P%>(%f%r,Error\ l%l\ in\ %m,%-Q)%r'
3199  let l = g:Xgetlist({'lines' : [
3200	      \ '(one.txt',
3201	      \ 'Error l4 in one.txt',
3202	      \ ') (two.txt',
3203	      \ 'Error l6 in two.txt',
3204	      \ ')',
3205	      \ 'Error l8 in one.txt'
3206	      \ ], 'efm' : efm_val})
3207  call assert_equal(3, len(l.items))
3208  call assert_equal('one.txt', bufname(l.items[0].bufnr))
3209  call assert_equal(4, l.items[0].lnum)
3210  call assert_equal('one.txt', l.items[0].text)
3211  call assert_equal('two.txt', bufname(l.items[1].bufnr))
3212  call assert_equal(6, l.items[1].lnum)
3213  call assert_equal('two.txt', l.items[1].text)
3214  call assert_equal('one.txt', bufname(l.items[2].bufnr))
3215  call assert_equal(8, l.items[2].lnum)
3216  call assert_equal('', l.items[2].text)
3217endfunc
3218
3219func Test_multifilestack()
3220  let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7']
3221  call writefile(lines, 'one.txt')
3222  call writefile(lines, 'two.txt')
3223  let save_efm = &efm
3224  set efm=%+P[%f],(%l\\,%c)\ %m,%-Q
3225
3226  call Xmultifilestack_tests('c')
3227  call Xmultifilestack_tests('l')
3228
3229  let &efm = save_efm
3230  call delete('one.txt')
3231  call delete('two.txt')
3232endfunc
3233
3234" Tests for per buffer 'efm' setting
3235func Test_perbuf_efm()
3236  call writefile(["File1-10-Line10"], 'one.txt')
3237  call writefile(["File2#20#Line20"], 'two.txt')
3238  set efm=%f#%l#%m
3239  new | only
3240  new
3241  setlocal efm=%f-%l-%m
3242  cfile one.txt
3243  wincmd w
3244  caddfile two.txt
3245
3246  let l = getqflist()
3247  call assert_equal(10, l[0].lnum)
3248  call assert_equal('Line20', l[1].text)
3249
3250  set efm&
3251  new | only
3252  call delete('one.txt')
3253  call delete('two.txt')
3254endfunc
3255
3256" Open multiple help windows using ":lhelpgrep
3257" This test used to crash Vim
3258func Test_Multi_LL_Help()
3259  new | only
3260  lhelpgrep window
3261  lopen
3262  e#
3263  lhelpgrep buffer
3264  call assert_equal(3, winnr('$'))
3265  call assert_true(len(getloclist(1)) != 0)
3266  call assert_true(len(getloclist(2)) != 0)
3267  new | only
3268endfunc
3269
3270" Tests for adding new quickfix lists using setqflist()
3271func XaddQf_tests(cchar)
3272  call s:setup_commands(a:cchar)
3273
3274  " Create a new list using ' ' for action
3275  call g:Xsetlist([], 'f')
3276  call g:Xsetlist([], ' ', {'title' : 'Test1'})
3277  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3278  call assert_equal(1, l.nr)
3279  call assert_equal('Test1', l.title)
3280
3281  " Create a new list using ' ' for action and '$' for 'nr'
3282  call g:Xsetlist([], 'f')
3283  call g:Xsetlist([], ' ', {'title' : 'Test2', 'nr' : '$'})
3284  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3285  call assert_equal(1, l.nr)
3286  call assert_equal('Test2', l.title)
3287
3288  " Create a new list using 'a' for action
3289  call g:Xsetlist([], 'f')
3290  call g:Xsetlist([], 'a', {'title' : 'Test3'})
3291  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3292  call assert_equal(1, l.nr)
3293  call assert_equal('Test3', l.title)
3294
3295  " Create a new list using 'a' for action and '$' for 'nr'
3296  call g:Xsetlist([], 'f')
3297  call g:Xsetlist([], 'a', {'title' : 'Test3', 'nr' : '$'})
3298  call g:Xsetlist([], 'a', {'title' : 'Test4'})
3299  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3300  call assert_equal(1, l.nr)
3301  call assert_equal('Test4', l.title)
3302
3303  " Adding a quickfix list should remove all the lists following the current
3304  " list.
3305  Xexpr "" | Xexpr "" | Xexpr ""
3306  silent! 10Xolder
3307  call g:Xsetlist([], ' ', {'title' : 'Test5'})
3308  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3309  call assert_equal(2, l.nr)
3310  call assert_equal('Test5', l.title)
3311
3312  " Add a quickfix list using '$' as the list number.
3313  let lastqf = g:Xgetlist({'nr':'$'}).nr
3314  silent! 99Xolder
3315  call g:Xsetlist([], ' ', {'nr' : '$', 'title' : 'Test6'})
3316  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3317  call assert_equal(lastqf + 1, l.nr)
3318  call assert_equal('Test6', l.title)
3319
3320  " Add a quickfix list using 'nr' set to one more than the quickfix
3321  " list size.
3322  let lastqf = g:Xgetlist({'nr':'$'}).nr
3323  silent! 99Xolder
3324  call g:Xsetlist([], ' ', {'nr' : lastqf + 1, 'title' : 'Test7'})
3325  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3326  call assert_equal(lastqf + 1, l.nr)
3327  call assert_equal('Test7', l.title)
3328
3329  " Add a quickfix list to a stack with 10 lists using 'nr' set to '$'
3330  exe repeat('Xexpr "" |', 9) . 'Xexpr ""'
3331  silent! 99Xolder
3332  call g:Xsetlist([], ' ', {'nr' : '$', 'title' : 'Test8'})
3333  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3334  call assert_equal(10, l.nr)
3335  call assert_equal('Test8', l.title)
3336
3337  " Add a quickfix list using 'nr' set to a value greater than 10
3338  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : 12, 'title' : 'Test9'}))
3339
3340  " Try adding a quickfix list with 'nr' set to a value greater than the
3341  " quickfix list size but less than 10.
3342  call g:Xsetlist([], 'f')
3343  Xexpr "" | Xexpr "" | Xexpr ""
3344  silent! 99Xolder
3345  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : 8, 'title' : 'Test10'}))
3346
3347  " Add a quickfix list using 'nr' set to a some string or list
3348  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : [1,2], 'title' : 'Test11'}))
3349endfunc
3350
3351func Test_add_qf()
3352  call XaddQf_tests('c')
3353  call XaddQf_tests('l')
3354endfunc
3355
3356" Test for getting the quickfix list items from some text without modifying
3357" the quickfix stack
3358func XgetListFromLines(cchar)
3359  call s:setup_commands(a:cchar)
3360  call g:Xsetlist([], 'f')
3361
3362  let l = g:Xgetlist({'lines' : ["File2:20:Line20", "File2:30:Line30"]}).items
3363  call assert_equal(2, len(l))
3364  call assert_equal(30, l[1].lnum)
3365
3366  call assert_equal({}, g:Xgetlist({'lines' : 10}))
3367  call assert_equal({}, g:Xgetlist({'lines' : 'File1:10:Line10'}))
3368  call assert_equal([], g:Xgetlist({'lines' : []}).items)
3369  call assert_equal([], g:Xgetlist({'lines' : [10, 20]}).items)
3370
3371  " Parse text using a custom efm
3372  set efm&
3373  let l = g:Xgetlist({'lines':['File3#30#Line30'], 'efm' : '%f#%l#%m'}).items
3374  call assert_equal('Line30', l[0].text)
3375  let l = g:Xgetlist({'lines':['File3:30:Line30'], 'efm' : '%f-%l-%m'}).items
3376  call assert_equal('File3:30:Line30', l[0].text)
3377  let l = g:Xgetlist({'lines':['File3:30:Line30'], 'efm' : [1,2]})
3378  call assert_equal({}, l)
3379  call assert_fails("call g:Xgetlist({'lines':['abc'], 'efm':'%2'})", 'E376:')
3380  call assert_fails("call g:Xgetlist({'lines':['abc'], 'efm':''})", 'E378:')
3381
3382  " Make sure that the quickfix stack is not modified
3383  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
3384endfunc
3385
3386func Test_get_list_from_lines()
3387  call XgetListFromLines('c')
3388  call XgetListFromLines('l')
3389endfunc
3390
3391" Tests for the quickfix list id
3392func Xqfid_tests(cchar)
3393  call s:setup_commands(a:cchar)
3394
3395  call g:Xsetlist([], 'f')
3396  call assert_equal(0, g:Xgetlist({'id':0}).id)
3397  Xexpr ''
3398  let start_id = g:Xgetlist({'id' : 0}).id
3399  Xexpr '' | Xexpr ''
3400  Xolder
3401  call assert_equal(start_id, g:Xgetlist({'id':0, 'nr':1}).id)
3402  call assert_equal(start_id + 1, g:Xgetlist({'id':0, 'nr':0}).id)
3403  call assert_equal(start_id + 2, g:Xgetlist({'id':0, 'nr':'$'}).id)
3404  call assert_equal(0, g:Xgetlist({'id':0, 'nr':99}).id)
3405  call assert_equal(2, g:Xgetlist({'id':start_id + 1, 'nr':0}).nr)
3406  call assert_equal(0, g:Xgetlist({'id':99, 'nr':0}).id)
3407  call assert_equal(0, g:Xgetlist({'id':"abc", 'nr':0}).id)
3408
3409  call g:Xsetlist([], 'a', {'id':start_id, 'context':[1,2]})
3410  call assert_equal([1,2], g:Xgetlist({'nr':1, 'context':1}).context)
3411  call g:Xsetlist([], 'a', {'id':start_id+1, 'lines':['F1:10:L10']})
3412  call assert_equal('L10', g:Xgetlist({'nr':2, 'items':1}).items[0].text)
3413  call assert_equal(-1, g:Xsetlist([], 'a', {'id':999, 'title':'Vim'}))
3414  call assert_equal(-1, g:Xsetlist([], 'a', {'id':'abc', 'title':'Vim'}))
3415
3416  let qfid = g:Xgetlist({'id':0, 'nr':0})
3417  call g:Xsetlist([], 'f')
3418  call assert_equal(0, g:Xgetlist({'id':qfid, 'nr':0}).id)
3419endfunc
3420
3421func Test_qf_id()
3422  call Xqfid_tests('c')
3423  call Xqfid_tests('l')
3424endfunc
3425
3426func Xqfjump_tests(cchar)
3427  call s:setup_commands(a:cchar)
3428
3429  call writefile(["Line1\tFoo", "Line2"], 'F1')
3430  call writefile(["Line1\tBar", "Line2"], 'F2')
3431  call writefile(["Line1\tBaz", "Line2"], 'F3')
3432
3433  call g:Xsetlist([], 'f')
3434
3435  " Tests for
3436  "   Jumping to a line using a pattern
3437  "   Jumping to a column greater than the last column in a line
3438  "   Jumping to a line greater than the last line in the file
3439  let l = []
3440  for i in range(1, 7)
3441    call add(l, {})
3442  endfor
3443  let l[0].filename='F1'
3444  let l[0].pattern='Line1'
3445  let l[1].filename='F2'
3446  let l[1].pattern='Line1'
3447  let l[2].filename='F3'
3448  let l[2].pattern='Line1'
3449  let l[3].filename='F3'
3450  let l[3].lnum=1
3451  let l[3].col=9
3452  let l[3].vcol=1
3453  let l[4].filename='F3'
3454  let l[4].lnum=99
3455  let l[5].filename='F3'
3456  let l[5].lnum=1
3457  let l[5].col=99
3458  let l[5].vcol=1
3459  let l[6].filename='F3'
3460  let l[6].pattern='abcxyz'
3461
3462  call g:Xsetlist([], ' ', {'items' : l})
3463  Xopen | only
3464  2Xnext
3465  call assert_equal(3, g:Xgetlist({'idx' : 0}).idx)
3466  call assert_equal('F3', @%)
3467  Xnext
3468  call assert_equal(7, col('.'))
3469  Xnext
3470  call assert_equal(2, line('.'))
3471  Xnext
3472  call assert_equal(9, col('.'))
3473  2
3474  Xnext
3475  call assert_equal(2, line('.'))
3476
3477  if a:cchar == 'l'
3478    " When jumping to a location list entry in the location list window and
3479    " no usable windows are available, then a new window should be opened.
3480    enew! | new | only
3481    call g:Xsetlist([], 'f')
3482    setlocal buftype=nofile
3483    new
3484    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']})
3485    Xopen
3486    let winid = win_getid()
3487    wincmd p
3488    close
3489    call win_gotoid(winid)
3490    Xnext
3491    call assert_equal(3, winnr('$'))
3492    call assert_equal(1, winnr())
3493    call assert_equal(2, line('.'))
3494
3495    " When jumping to an entry in the location list window and the window
3496    " associated with the location list is not present and a window containing
3497    " the file is already present, then that window should be used.
3498    close
3499    belowright new
3500    call g:Xsetlist([], 'f')
3501    edit F3
3502    call win_gotoid(winid)
3503    Xlast
3504    call assert_equal(3, winnr())
3505    call assert_equal(6, g:Xgetlist({'size' : 1}).size)
3506    call assert_equal(winid, g:Xgetlist({'winid' : 1}).winid)
3507  endif
3508
3509  " Cleanup
3510  enew!
3511  new | only
3512
3513  call delete('F1')
3514  call delete('F2')
3515  call delete('F3')
3516endfunc
3517
3518func Test_qfjump()
3519  call Xqfjump_tests('c')
3520  call Xqfjump_tests('l')
3521endfunc
3522
3523" Tests for the getqflist() and getloclist() functions when the list is not
3524" present or is empty
3525func Xgetlist_empty_tests(cchar)
3526  call s:setup_commands(a:cchar)
3527
3528  " Empty quickfix stack
3529  call g:Xsetlist([], 'f')
3530  call assert_equal('', g:Xgetlist({'context' : 0}).context)
3531  call assert_equal(0, g:Xgetlist({'id' : 0}).id)
3532  call assert_equal(0, g:Xgetlist({'idx' : 0}).idx)
3533  call assert_equal([], g:Xgetlist({'items' : 0}).items)
3534  call assert_equal(0, g:Xgetlist({'nr' : 0}).nr)
3535  call assert_equal(0, g:Xgetlist({'size' : 0}).size)
3536  call assert_equal('', g:Xgetlist({'title' : 0}).title)
3537  call assert_equal(0, g:Xgetlist({'winid' : 0}).winid)
3538  call assert_equal(0, g:Xgetlist({'changedtick' : 0}).changedtick)
3539  if a:cchar == 'c'
3540    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0,
3541		  \ 'items' : [], 'nr' : 0, 'size' : 0, 'qfbufnr' : 0,
3542		  \ 'title' : '', 'winid' : 0, 'changedtick': 0,
3543                  \ 'quickfixtextfunc' : ''}, g:Xgetlist({'all' : 0}))
3544  else
3545    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0,
3546		\ 'items' : [], 'nr' : 0, 'size' : 0, 'title' : '',
3547		\ 'winid' : 0, 'changedtick': 0, 'filewinid' : 0,
3548		\ 'qfbufnr' : 0, 'quickfixtextfunc' : ''},
3549		\ g:Xgetlist({'all' : 0}))
3550  endif
3551
3552  " Quickfix window with empty stack
3553  silent! Xopen
3554  let qfwinid = (a:cchar == 'c') ? win_getid() : 0
3555  let qfbufnr = (a:cchar == 'c') ? bufnr('') : 0
3556  call assert_equal(qfwinid, g:Xgetlist({'winid' : 0}).winid)
3557  Xclose
3558
3559  " Empty quickfix list
3560  Xexpr ""
3561  call assert_equal('', g:Xgetlist({'context' : 0}).context)
3562  call assert_notequal(0, g:Xgetlist({'id' : 0}).id)
3563  call assert_equal(0, g:Xgetlist({'idx' : 0}).idx)
3564  call assert_equal([], g:Xgetlist({'items' : 0}).items)
3565  call assert_notequal(0, g:Xgetlist({'nr' : 0}).nr)
3566  call assert_equal(0, g:Xgetlist({'size' : 0}).size)
3567  call assert_notequal('', g:Xgetlist({'title' : 0}).title)
3568  call assert_equal(0, g:Xgetlist({'winid' : 0}).winid)
3569  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3570
3571  let qfid = g:Xgetlist({'id' : 0}).id
3572  call g:Xsetlist([], 'f')
3573
3574  " Non-existing quickfix identifier
3575  call assert_equal('', g:Xgetlist({'id' : qfid, 'context' : 0}).context)
3576  call assert_equal(0, g:Xgetlist({'id' : qfid}).id)
3577  call assert_equal(0, g:Xgetlist({'id' : qfid, 'idx' : 0}).idx)
3578  call assert_equal([], g:Xgetlist({'id' : qfid, 'items' : 0}).items)
3579  call assert_equal(0, g:Xgetlist({'id' : qfid, 'nr' : 0}).nr)
3580  call assert_equal(0, g:Xgetlist({'id' : qfid, 'size' : 0}).size)
3581  call assert_equal('', g:Xgetlist({'id' : qfid, 'title' : 0}).title)
3582  call assert_equal(0, g:Xgetlist({'id' : qfid, 'winid' : 0}).winid)
3583  call assert_equal(0, g:Xgetlist({'id' : qfid, 'changedtick' : 0}).changedtick)
3584  if a:cchar == 'c'
3585    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
3586		\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
3587		\ 'qfbufnr' : qfbufnr, 'quickfixtextfunc' : '',
3588		\ 'changedtick' : 0}, g:Xgetlist({'id' : qfid, 'all' : 0}))
3589  else
3590    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
3591		\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
3592		\ 'changedtick' : 0, 'filewinid' : 0, 'qfbufnr' : 0,
3593                \ 'quickfixtextfunc' : ''},
3594		\ g:Xgetlist({'id' : qfid, 'all' : 0}))
3595  endif
3596
3597  " Non-existing quickfix list number
3598  call assert_equal('', g:Xgetlist({'nr' : 5, 'context' : 0}).context)
3599  call assert_equal(0, g:Xgetlist({'nr' : 5}).nr)
3600  call assert_equal(0, g:Xgetlist({'nr' : 5, 'idx' : 0}).idx)
3601  call assert_equal([], g:Xgetlist({'nr' : 5, 'items' : 0}).items)
3602  call assert_equal(0, g:Xgetlist({'nr' : 5, 'id' : 0}).id)
3603  call assert_equal(0, g:Xgetlist({'nr' : 5, 'size' : 0}).size)
3604  call assert_equal('', g:Xgetlist({'nr' : 5, 'title' : 0}).title)
3605  call assert_equal(0, g:Xgetlist({'nr' : 5, 'winid' : 0}).winid)
3606  call assert_equal(0, g:Xgetlist({'nr' : 5, 'changedtick' : 0}).changedtick)
3607  if a:cchar == 'c'
3608    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
3609		\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
3610		\ 'changedtick' : 0, 'qfbufnr' : qfbufnr,
3611                \ 'quickfixtextfunc' : ''}, g:Xgetlist({'nr' : 5, 'all' : 0}))
3612  else
3613    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
3614		\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
3615		\ 'changedtick' : 0, 'filewinid' : 0, 'qfbufnr' : 0,
3616                \ 'quickfixtextfunc' : ''}, g:Xgetlist({'nr' : 5, 'all' : 0}))
3617  endif
3618endfunc
3619
3620func Test_getqflist()
3621  call Xgetlist_empty_tests('c')
3622  call Xgetlist_empty_tests('l')
3623endfunc
3624
3625func Test_getqflist_invalid_nr()
3626  " The following commands used to crash Vim
3627  cexpr ""
3628  call getqflist({'nr' : $XXX_DOES_NOT_EXIST_XXX})
3629
3630  " Cleanup
3631  call setqflist([], 'r')
3632endfunc
3633
3634" Tests for the quickfix/location list changedtick
3635func Xqftick_tests(cchar)
3636  call s:setup_commands(a:cchar)
3637
3638  call g:Xsetlist([], 'f')
3639
3640  Xexpr "F1:10:Line10"
3641  let qfid = g:Xgetlist({'id' : 0}).id
3642  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3643  Xaddexpr "F2:20:Line20\nF2:21:Line21"
3644  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
3645  call g:Xsetlist([], 'a', {'lines' : ["F3:30:Line30", "F3:31:Line31"]})
3646  call assert_equal(3, g:Xgetlist({'changedtick' : 0}).changedtick)
3647  call g:Xsetlist([], 'r', {'lines' : ["F4:40:Line40"]})
3648  call assert_equal(4, g:Xgetlist({'changedtick' : 0}).changedtick)
3649  call g:Xsetlist([], 'a', {'title' : 'New Title'})
3650  call assert_equal(5, g:Xgetlist({'changedtick' : 0}).changedtick)
3651
3652  enew!
3653  call append(0, ["F5:50:L50", "F6:60:L60"])
3654  Xaddbuffer
3655  call assert_equal(6, g:Xgetlist({'changedtick' : 0}).changedtick)
3656  enew!
3657
3658  call g:Xsetlist([], 'a', {'context' : {'bus' : 'pci'}})
3659  call assert_equal(7, g:Xgetlist({'changedtick' : 0}).changedtick)
3660  call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'},
3661	      \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], 'a')
3662  call assert_equal(8, g:Xgetlist({'changedtick' : 0}).changedtick)
3663  call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'},
3664	      \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], ' ')
3665  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3666  call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'},
3667	      \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], 'r')
3668  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
3669
3670  call writefile(["F8:80:L80", "F8:81:L81"], "Xone")
3671  Xfile Xone
3672  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3673  Xaddfile Xone
3674  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
3675
3676  " Test case for updating a non-current quickfix list
3677  call g:Xsetlist([], 'f')
3678  Xexpr "F1:1:L1"
3679  Xexpr "F2:2:L2"
3680  call g:Xsetlist([], 'a', {'nr' : 1, "lines" : ["F10:10:L10"]})
3681  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3682  call assert_equal(2, g:Xgetlist({'nr' : 1, 'changedtick' : 0}).changedtick)
3683
3684  call delete("Xone")
3685endfunc
3686
3687func Test_qf_tick()
3688  call Xqftick_tests('c')
3689  call Xqftick_tests('l')
3690endfunc
3691
3692" Test helpgrep with lang specifier
3693func Xtest_helpgrep_with_lang_specifier(cchar)
3694  call s:setup_commands(a:cchar)
3695  Xhelpgrep Vim@en
3696  call assert_equal('help', &filetype)
3697  call assert_notequal(0, g:Xgetlist({'nr' : '$'}).nr)
3698  new | only
3699endfunc
3700
3701func Test_helpgrep_with_lang_specifier()
3702  call Xtest_helpgrep_with_lang_specifier('c')
3703  call Xtest_helpgrep_with_lang_specifier('l')
3704endfunc
3705
3706" The following test used to crash Vim.
3707" Open the location list window and close the regular window associated with
3708" the location list. When the garbage collection runs now, it incorrectly
3709" marks the location list context as not in use and frees the context.
3710func Test_ll_window_ctx()
3711  call setloclist(0, [], 'f')
3712  call setloclist(0, [], 'a', {'context' : []})
3713  lopen | only
3714  call test_garbagecollect_now()
3715  echo getloclist(0, {'context' : 1}).context
3716  enew | only
3717endfunc
3718
3719" The following test used to crash vim
3720func Test_lfile_crash()
3721  sp Xtest
3722  au QuickFixCmdPre * bw
3723  call assert_fails('lfile', 'E40:')
3724  au! QuickFixCmdPre
3725endfunc
3726
3727" The following test used to crash vim
3728func Test_lbuffer_crash()
3729  sv Xtest
3730  augroup QF_Test
3731    au!
3732    au * * bw
3733  augroup END
3734  lbuffer
3735  augroup QF_Test
3736    au!
3737  augroup END
3738endfunc
3739
3740" The following test used to crash vim
3741func Test_lexpr_crash()
3742  augroup QF_Test
3743    au!
3744    au * * call setloclist(0, [], 'f')
3745  augroup END
3746  lexpr ""
3747  augroup QF_Test
3748    au!
3749  augroup END
3750
3751  enew | only
3752  augroup QF_Test
3753    au!
3754    au BufNew * call setloclist(0, [], 'f')
3755  augroup END
3756  lexpr 'x:1:x'
3757  augroup QF_Test
3758    au!
3759  augroup END
3760
3761  enew | only
3762  lexpr ''
3763  lopen
3764  augroup QF_Test
3765    au!
3766    au FileType * call setloclist(0, [], 'f')
3767  augroup END
3768  lexpr ''
3769  augroup QF_Test
3770    au!
3771  augroup END
3772endfunc
3773
3774" The following test used to crash Vim
3775func Test_lvimgrep_crash()
3776  sv Xtest
3777  augroup QF_Test
3778    au!
3779    au * * call setloclist(0, [], 'f')
3780  augroup END
3781  lvimgrep quickfix test_quickfix.vim
3782  augroup QF_Test
3783    au!
3784  augroup END
3785
3786  new | only
3787  augroup QF_Test
3788    au!
3789    au BufEnter * call setloclist(0, [], 'r')
3790  augroup END
3791  call assert_fails('lvimgrep Test_lvimgrep_crash *', 'E926:')
3792  augroup QF_Test
3793    au!
3794  augroup END
3795
3796  enew | only
3797endfunc
3798
3799func Test_lvimgrep_crash2()
3800  au BufNewFile x sfind
3801  call assert_fails('lvimgrep x x', 'E471:')
3802  call assert_fails('lvimgrep x x x', 'E471:')
3803
3804  au! BufNewFile
3805endfunc
3806
3807" Test for the position of the quickfix and location list window
3808func Test_qfwin_pos()
3809  " Open two windows
3810  new | only
3811  new
3812  cexpr ['F1:10:L10']
3813  copen
3814  " Quickfix window should be the bottom most window
3815  call assert_equal(3, winnr())
3816  close
3817  " Open at the very top
3818  wincmd t
3819  topleft copen
3820  call assert_equal(1, winnr())
3821  close
3822  " open left of the current window
3823  wincmd t
3824  below new
3825  leftabove copen
3826  call assert_equal(2, winnr())
3827  close
3828  " open right of the current window
3829  rightbelow copen
3830  call assert_equal(3, winnr())
3831  close
3832endfunc
3833
3834" Tests for quickfix/location lists changed by autocommands when
3835" :vimgrep/:lvimgrep commands are running.
3836func Test_vimgrep_autocmd()
3837  call setqflist([], 'f')
3838  call writefile(['stars'], 'Xtest1.txt')
3839  call writefile(['stars'], 'Xtest2.txt')
3840
3841  " Test 1:
3842  " When searching for a pattern using :vimgrep, if the quickfix list is
3843  " changed by an autocmd, the results should be added to the correct quickfix
3844  " list.
3845  autocmd BufRead Xtest2.txt cexpr '' | cexpr ''
3846  silent vimgrep stars Xtest*.txt
3847  call assert_equal(1, getqflist({'nr' : 0}).nr)
3848  call assert_equal(3, getqflist({'nr' : '$'}).nr)
3849  call assert_equal('Xtest2.txt', bufname(getqflist()[1].bufnr))
3850  au! BufRead Xtest2.txt
3851
3852  " Test 2:
3853  " When searching for a pattern using :vimgrep, if the quickfix list is
3854  " freed, then a error should be given.
3855  silent! %bwipe!
3856  call setqflist([], 'f')
3857  autocmd BufRead Xtest2.txt for i in range(10) | cexpr '' | endfor
3858  call assert_fails('vimgrep stars Xtest*.txt', 'E925:')
3859  au! BufRead Xtest2.txt
3860
3861  " Test 3:
3862  " When searching for a pattern using :lvimgrep, if the location list is
3863  " freed, then the command should error out.
3864  silent! %bwipe!
3865  let g:save_winid = win_getid()
3866  autocmd BufRead Xtest2.txt call setloclist(g:save_winid, [], 'f')
3867  call assert_fails('lvimgrep stars Xtest*.txt', 'E926:')
3868  au! BufRead Xtest2.txt
3869
3870  call delete('Xtest1.txt')
3871  call delete('Xtest2.txt')
3872  call setqflist([], 'f')
3873endfunc
3874
3875" Test for an autocmd changing the current directory when running vimgrep
3876func Xvimgrep_autocmd_cd(cchar)
3877  call s:setup_commands(a:cchar)
3878
3879  %bwipe
3880  let save_cwd = getcwd()
3881
3882  augroup QF_Test
3883    au!
3884    autocmd BufRead * silent cd %:p:h
3885  augroup END
3886
3887  10Xvimgrep /vim/ Xdir/**
3888  let l = g:Xgetlist()
3889  call assert_equal('f1.txt', bufname(l[0].bufnr))
3890  call assert_equal('f2.txt', fnamemodify(bufname(l[2].bufnr), ':t'))
3891
3892  augroup QF_Test
3893    au!
3894  augroup END
3895
3896  exe 'cd ' . save_cwd
3897endfunc
3898
3899func Test_vimgrep_autocmd_cd()
3900  call mkdir('Xdir/a', 'p')
3901  call mkdir('Xdir/b', 'p')
3902  call writefile(['a_L1_vim', 'a_L2_vim'], 'Xdir/a/f1.txt')
3903  call writefile(['b_L1_vim', 'b_L2_vim'], 'Xdir/b/f2.txt')
3904  call Xvimgrep_autocmd_cd('c')
3905  call Xvimgrep_autocmd_cd('l')
3906  %bwipe
3907  call delete('Xdir', 'rf')
3908endfunc
3909
3910" The following test used to crash Vim
3911func Test_lhelpgrep_autocmd()
3912  lhelpgrep quickfix
3913  autocmd QuickFixCmdPost * call setloclist(0, [], 'f')
3914  lhelpgrep buffer
3915  call assert_equal('help', &filetype)
3916  call assert_equal(0, getloclist(0, {'nr' : '$'}).nr)
3917  lhelpgrep tabpage
3918  call assert_equal('help', &filetype)
3919  call assert_equal(1, getloclist(0, {'nr' : '$'}).nr)
3920  au! QuickFixCmdPost
3921
3922  new | only
3923  augroup QF_Test
3924    au!
3925    au BufEnter * call setqflist([], 'f')
3926  augroup END
3927  call assert_fails('helpgrep quickfix', 'E925:')
3928  augroup QF_Test
3929    au! BufEnter
3930  augroup END
3931
3932  new | only
3933  augroup QF_Test
3934    au!
3935    au BufEnter * call setqflist([], 'r')
3936  augroup END
3937  call assert_fails('helpgrep quickfix', 'E925:')
3938  augroup QF_Test
3939    au! BufEnter
3940  augroup END
3941
3942  new | only
3943  augroup QF_Test
3944    au!
3945    au BufEnter * call setloclist(0, [], 'r')
3946  augroup END
3947  call assert_fails('lhelpgrep quickfix', 'E926:')
3948  augroup QF_Test
3949    au! BufEnter
3950  augroup END
3951
3952  new | only
3953endfunc
3954
3955" Test for shortening/simplifying the file name when opening the
3956" quickfix window or when displaying the quickfix list
3957func Test_shorten_fname()
3958  CheckUnix
3959  %bwipe
3960  " Create a quickfix list with a absolute path filename
3961  let fname = getcwd() . '/test_quickfix.vim'
3962  call setqflist([], ' ', {'lines':[fname . ":20:Line20"], 'efm':'%f:%l:%m'})
3963  call assert_equal(fname, bufname('test_quickfix.vim'))
3964  " Opening the quickfix window should simplify the file path
3965  cwindow
3966  call assert_equal('test_quickfix.vim', bufname('test_quickfix.vim'))
3967  cclose
3968  %bwipe
3969  " Create a quickfix list with a absolute path filename
3970  call setqflist([], ' ', {'lines':[fname . ":20:Line20"], 'efm':'%f:%l:%m'})
3971  call assert_equal(fname, bufname('test_quickfix.vim'))
3972  " Displaying the quickfix list should simplify the file path
3973  silent! clist
3974  call assert_equal('test_quickfix.vim', bufname('test_quickfix.vim'))
3975endfunc
3976
3977" Quickfix title tests
3978" In the below tests, 'exe "cmd"' is used to invoke the quickfix commands.
3979" Otherwise due to indentation, the title is set with spaces at the beginning
3980" of the command.
3981func Test_qftitle()
3982  call writefile(["F1:1:Line1"], 'Xerr')
3983
3984  " :cexpr
3985  exe "cexpr readfile('Xerr')"
3986  call assert_equal(":cexpr readfile('Xerr')", getqflist({'title' : 1}).title)
3987
3988  " :cgetexpr
3989  exe "cgetexpr readfile('Xerr')"
3990  call assert_equal(":cgetexpr readfile('Xerr')",
3991					\ getqflist({'title' : 1}).title)
3992
3993  " :caddexpr
3994  call setqflist([], 'f')
3995  exe "caddexpr readfile('Xerr')"
3996  call assert_equal(":caddexpr readfile('Xerr')",
3997					\ getqflist({'title' : 1}).title)
3998
3999  " :cbuffer
4000  new Xerr
4001  exe "cbuffer"
4002  call assert_equal(':cbuffer (Xerr)', getqflist({'title' : 1}).title)
4003
4004  " :cgetbuffer
4005  edit Xerr
4006  exe "cgetbuffer"
4007  call assert_equal(':cgetbuffer (Xerr)', getqflist({'title' : 1}).title)
4008
4009  " :caddbuffer
4010  call setqflist([], 'f')
4011  edit Xerr
4012  exe "caddbuffer"
4013  call assert_equal(':caddbuffer (Xerr)', getqflist({'title' : 1}).title)
4014
4015  " :cfile
4016  exe "cfile Xerr"
4017  call assert_equal(':cfile Xerr', getqflist({'title' : 1}).title)
4018
4019  " :cgetfile
4020  exe "cgetfile Xerr"
4021  call assert_equal(':cgetfile Xerr', getqflist({'title' : 1}).title)
4022
4023  " :caddfile
4024  call setqflist([], 'f')
4025  exe "caddfile Xerr"
4026  call assert_equal(':caddfile Xerr', getqflist({'title' : 1}).title)
4027
4028  " :grep
4029  set grepprg=internal
4030  exe "grep F1 Xerr"
4031  call assert_equal(':grep F1 Xerr', getqflist({'title' : 1}).title)
4032
4033  " :grepadd
4034  call setqflist([], 'f')
4035  exe "grepadd F1 Xerr"
4036  call assert_equal(':grepadd F1 Xerr', getqflist({'title' : 1}).title)
4037  set grepprg&vim
4038
4039  " :vimgrep
4040  exe "vimgrep F1 Xerr"
4041  call assert_equal(':vimgrep F1 Xerr', getqflist({'title' : 1}).title)
4042
4043  " :vimgrepadd
4044  call setqflist([], 'f')
4045  exe "vimgrepadd F1 Xerr"
4046  call assert_equal(':vimgrepadd F1 Xerr', getqflist({'title' : 1}).title)
4047
4048  call setqflist(['F1:10:L10'], ' ')
4049  call assert_equal(':setqflist()', getqflist({'title' : 1}).title)
4050
4051  call setqflist([], 'f')
4052  call setqflist(['F1:10:L10'], 'a')
4053  call assert_equal(':setqflist()', getqflist({'title' : 1}).title)
4054
4055  call setqflist([], 'f')
4056  call setqflist(['F1:10:L10'], 'r')
4057  call assert_equal(':setqflist()', getqflist({'title' : 1}).title)
4058
4059  close
4060  call delete('Xerr')
4061
4062  call setqflist([], ' ', {'title' : 'Errors'})
4063  copen
4064  call assert_equal('Errors', w:quickfix_title)
4065  call setqflist([], 'r', {'items' : [{'filename' : 'a.c', 'lnum' : 10}]})
4066  call assert_equal('Errors', w:quickfix_title)
4067  cclose
4068endfunc
4069
4070func Test_lbuffer_with_bwipe()
4071  new
4072  new
4073  augroup nasty
4074    au * * bwipe
4075  augroup END
4076  lbuffer
4077  augroup nasty
4078    au!
4079  augroup END
4080endfunc
4081
4082" Test for an autocmd freeing the quickfix/location list when cexpr/lexpr is
4083" running
4084func Xexpr_acmd_freelist(cchar)
4085  call s:setup_commands(a:cchar)
4086
4087  " This was using freed memory.
4088  augroup nasty
4089    au * * call g:Xsetlist([], 'f')
4090  augroup END
4091  Xexpr "x"
4092  augroup nasty
4093    au!
4094  augroup END
4095endfunc
4096
4097func Test_cexpr_acmd_freelist()
4098  call Xexpr_acmd_freelist('c')
4099  call Xexpr_acmd_freelist('l')
4100endfunc
4101
4102" Test for commands that create a new quickfix/location list and jump to the
4103" first error automatically.
4104func Xjumpto_first_error_test(cchar)
4105  call s:setup_commands(a:cchar)
4106
4107  call s:create_test_file('Xtestfile1')
4108  call s:create_test_file('Xtestfile2')
4109  let l = ['Xtestfile1:2:Line2', 'Xtestfile2:4:Line4']
4110
4111  " Test for cexpr/lexpr
4112  enew
4113  Xexpr l
4114  call assert_equal('Xtestfile1', @%)
4115  call assert_equal(2, line('.'))
4116
4117  " Test for cfile/lfile
4118  enew
4119  call writefile(l, 'Xerr')
4120  Xfile Xerr
4121  call assert_equal('Xtestfile1', @%)
4122  call assert_equal(2, line('.'))
4123
4124  " Test for cbuffer/lbuffer
4125  edit Xerr
4126  Xbuffer
4127  call assert_equal('Xtestfile1', @%)
4128  call assert_equal(2, line('.'))
4129
4130  call delete('Xerr')
4131  call delete('Xtestfile1')
4132  call delete('Xtestfile2')
4133endfunc
4134
4135func Test_jumpto_first_error()
4136  call Xjumpto_first_error_test('c')
4137  call Xjumpto_first_error_test('l')
4138endfunc
4139
4140" Test for a quickfix autocmd changing the quickfix/location list before
4141" jumping to the first error in the new list.
4142func Xautocmd_changelist(cchar)
4143  call s:setup_commands(a:cchar)
4144
4145  " Test for cfile/lfile
4146  call s:create_test_file('Xtestfile1')
4147  call s:create_test_file('Xtestfile2')
4148  Xexpr 'Xtestfile1:2:Line2'
4149  autocmd QuickFixCmdPost * Xolder
4150  call writefile(['Xtestfile2:4:Line4'], 'Xerr')
4151  Xfile Xerr
4152  call assert_equal('Xtestfile2', @%)
4153  call assert_equal(4, line('.'))
4154  autocmd! QuickFixCmdPost
4155
4156  " Test for cbuffer/lbuffer
4157  call g:Xsetlist([], 'f')
4158  Xexpr 'Xtestfile1:2:Line2'
4159  autocmd QuickFixCmdPost * Xolder
4160  call writefile(['Xtestfile2:4:Line4'], 'Xerr')
4161  edit Xerr
4162  Xbuffer
4163  call assert_equal('Xtestfile2', @%)
4164  call assert_equal(4, line('.'))
4165  autocmd! QuickFixCmdPost
4166
4167  " Test for cexpr/lexpr
4168  call g:Xsetlist([], 'f')
4169  Xexpr 'Xtestfile1:2:Line2'
4170  autocmd QuickFixCmdPost * Xolder
4171  Xexpr 'Xtestfile2:4:Line4'
4172  call assert_equal('Xtestfile2', @%)
4173  call assert_equal(4, line('.'))
4174  autocmd! QuickFixCmdPost
4175
4176  " The grepprg may not be set on non-Unix systems
4177  if has('unix')
4178    " Test for grep/lgrep
4179    call g:Xsetlist([], 'f')
4180    Xexpr 'Xtestfile1:2:Line2'
4181    autocmd QuickFixCmdPost * Xolder
4182    silent Xgrep Line5 Xtestfile2
4183    call assert_equal('Xtestfile2', @%)
4184    call assert_equal(5, line('.'))
4185    autocmd! QuickFixCmdPost
4186  endif
4187
4188  " Test for vimgrep/lvimgrep
4189  call g:Xsetlist([], 'f')
4190  Xexpr 'Xtestfile1:2:Line2'
4191  autocmd QuickFixCmdPost * Xolder
4192  silent Xvimgrep Line5 Xtestfile2
4193  call assert_equal('Xtestfile2', @%)
4194  call assert_equal(5, line('.'))
4195  autocmd! QuickFixCmdPost
4196
4197  " Test for autocommands clearing the quickfix list before jumping to the
4198  " first error. This should not result in an error
4199  autocmd QuickFixCmdPost * call g:Xsetlist([], 'r')
4200  let v:errmsg = ''
4201  " Test for cfile/lfile
4202  Xfile Xerr
4203  call assert_true(v:errmsg !~# 'E42:')
4204  " Test for cbuffer/lbuffer
4205  edit Xerr
4206  Xbuffer
4207  call assert_true(v:errmsg !~# 'E42:')
4208  " Test for cexpr/lexpr
4209  Xexpr 'Xtestfile2:4:Line4'
4210  call assert_true(v:errmsg !~# 'E42:')
4211  " Test for grep/lgrep
4212  " The grepprg may not be set on non-Unix systems
4213  if has('unix')
4214    silent Xgrep Line5 Xtestfile2
4215    call assert_true(v:errmsg !~# 'E42:')
4216  endif
4217  " Test for vimgrep/lvimgrep
4218  call assert_fails('silent Xvimgrep Line5 Xtestfile2', 'E480:')
4219  autocmd! QuickFixCmdPost
4220
4221  call delete('Xerr')
4222  call delete('Xtestfile1')
4223  call delete('Xtestfile2')
4224endfunc
4225
4226func Test_autocmd_changelist()
4227  call Xautocmd_changelist('c')
4228  call Xautocmd_changelist('l')
4229endfunc
4230
4231" Tests for the ':filter /pat/ clist' command
4232func Test_filter_clist()
4233  cexpr ['Xfile1:10:10:Line 10', 'Xfile2:15:15:Line 15']
4234  call assert_equal([' 2 Xfile2:15 col 15: Line 15'],
4235			\ split(execute('filter /Line 15/ clist'), "\n"))
4236  call assert_equal([' 1 Xfile1:10 col 10: Line 10'],
4237			\ split(execute('filter /Xfile1/ clist'), "\n"))
4238  call assert_equal([], split(execute('filter /abc/ clist'), "\n"))
4239
4240  call setqflist([{'module' : 'abc', 'pattern' : 'pat1'},
4241			\ {'module' : 'pqr', 'pattern' : 'pat2'}], ' ')
4242  call assert_equal([' 2 pqr:pat2:  '],
4243			\ split(execute('filter /pqr/ clist'), "\n"))
4244  call assert_equal([' 1 abc:pat1:  '],
4245			\ split(execute('filter /pat1/ clist'), "\n"))
4246endfunc
4247
4248" Tests for the "CTRL-W <CR>" command.
4249func Xview_result_split_tests(cchar)
4250  call s:setup_commands(a:cchar)
4251
4252  " Test that "CTRL-W <CR>" in a qf/ll window fails with empty list.
4253  call g:Xsetlist([])
4254  Xopen
4255  let l:win_count = winnr('$')
4256  call assert_fails('execute "normal! \<C-W>\<CR>"', 'E42:')
4257  call assert_equal(l:win_count, winnr('$'))
4258  Xclose
4259endfunc
4260
4261func Test_view_result_split()
4262  call Xview_result_split_tests('c')
4263  call Xview_result_split_tests('l')
4264endfunc
4265
4266" Test that :cc sets curswant
4267func Test_curswant()
4268  helpgrep quickfix
4269  normal! llll
4270  1cc
4271  call assert_equal(getcurpos()[4], virtcol('.'))
4272  cclose | helpclose
4273endfunc
4274
4275" Test for opening a file from the quickfix window using CTRL-W <Enter>
4276" doesn't leave an empty buffer around.
4277func Test_splitview()
4278  call s:create_test_file('Xtestfile1')
4279  call s:create_test_file('Xtestfile2')
4280  new | only
4281  let last_bufnr = bufnr('Test_sv_1', 1)
4282  let l = ['Xtestfile1:2:Line2', 'Xtestfile2:4:Line4']
4283  cgetexpr l
4284  copen
4285  let numbufs = len(getbufinfo())
4286  exe "normal \<C-W>\<CR>"
4287  copen
4288  exe "normal j\<C-W>\<CR>"
4289  " Make sure new empty buffers are not created
4290  call assert_equal(numbufs, len(getbufinfo()))
4291  " Creating a new buffer should use the next available buffer number
4292  call assert_equal(last_bufnr + 4, bufnr("Test_sv_2", 1))
4293  bwipe Test_sv_1
4294  bwipe Test_sv_2
4295  new | only
4296
4297  " When split opening files from location list window, make sure that two
4298  " windows doesn't refer to the same location list
4299  lgetexpr l
4300  let locid = getloclist(0, {'id' : 0}).id
4301  lopen
4302  exe "normal \<C-W>\<CR>"
4303  call assert_notequal(locid, getloclist(0, {'id' : 0}).id)
4304  call assert_equal(0, getloclist(0, {'winid' : 0}).winid)
4305  new | only
4306
4307  " When split opening files from a helpgrep location list window, a new help
4308  " window should be opened with a copy of the location list.
4309  lhelpgrep window
4310  let locid = getloclist(0, {'id' : 0}).id
4311  lwindow
4312  exe "normal j\<C-W>\<CR>"
4313  call assert_notequal(locid, getloclist(0, {'id' : 0}).id)
4314  call assert_equal(0, getloclist(0, {'winid' : 0}).winid)
4315  new | only
4316
4317  " Using :split or :vsplit from a quickfix window should behave like a :new
4318  " or a :vnew command
4319  copen
4320  split
4321  call assert_equal(3, winnr('$'))
4322  let l = getwininfo()
4323  call assert_equal([0, 0, 1], [l[0].quickfix, l[1].quickfix, l[2].quickfix])
4324  close
4325  copen
4326  vsplit
4327  let l = getwininfo()
4328  call assert_equal([0, 0, 1], [l[0].quickfix, l[1].quickfix, l[2].quickfix])
4329  new | only
4330
4331  call delete('Xtestfile1')
4332  call delete('Xtestfile2')
4333endfunc
4334
4335" Test for parsing entries using visual screen column
4336func Test_viscol()
4337  enew
4338  call writefile(["Col1\tCol2\tCol3"], 'Xfile1')
4339  edit Xfile1
4340
4341  " Use byte offset for column number
4342  set efm&
4343  cexpr "Xfile1:1:5:XX\nXfile1:1:9:YY\nXfile1:1:20:ZZ"
4344  call assert_equal([5, 8], [col('.'), virtcol('.')])
4345  cnext
4346  call assert_equal([9, 12], [col('.'), virtcol('.')])
4347  cnext
4348  call assert_equal([14, 20], [col('.'), virtcol('.')])
4349
4350  " Use screen column offset for column number
4351  set efm=%f:%l:%v:%m
4352  cexpr "Xfile1:1:8:XX\nXfile1:1:12:YY\nXfile1:1:20:ZZ"
4353  call assert_equal([5, 8], [col('.'), virtcol('.')])
4354  cnext
4355  call assert_equal([9, 12], [col('.'), virtcol('.')])
4356  cnext
4357  call assert_equal([14, 20], [col('.'), virtcol('.')])
4358  cexpr "Xfile1:1:6:XX\nXfile1:1:15:YY\nXfile1:1:24:ZZ"
4359  call assert_equal([5, 8], [col('.'), virtcol('.')])
4360  cnext
4361  call assert_equal([10, 16], [col('.'), virtcol('.')])
4362  cnext
4363  call assert_equal([14, 20], [col('.'), virtcol('.')])
4364
4365  enew
4366  call writefile(["Col1\täü\töß\tCol4"], 'Xfile1')
4367
4368  " Use byte offset for column number
4369  set efm&
4370  cexpr "Xfile1:1:8:XX\nXfile1:1:11:YY\nXfile1:1:16:ZZ"
4371  call assert_equal([8, 10], [col('.'), virtcol('.')])
4372  cnext
4373  call assert_equal([11, 17], [col('.'), virtcol('.')])
4374  cnext
4375  call assert_equal([16, 25], [col('.'), virtcol('.')])
4376
4377  " Use screen column offset for column number
4378  set efm=%f:%l:%v:%m
4379  cexpr "Xfile1:1:10:XX\nXfile1:1:17:YY\nXfile1:1:25:ZZ"
4380  call assert_equal([8, 10], [col('.'), virtcol('.')])
4381  cnext
4382  call assert_equal([11, 17], [col('.'), virtcol('.')])
4383  cnext
4384  call assert_equal([16, 25], [col('.'), virtcol('.')])
4385
4386  enew | only
4387  set efm&
4388  call delete('Xfile1')
4389endfunc
4390
4391" Test for the quickfix window buffer
4392func Xqfbuf_test(cchar)
4393  call s:setup_commands(a:cchar)
4394
4395  " Quickfix buffer should be reused across closing and opening a quickfix
4396  " window
4397  Xexpr "F1:10:Line10"
4398  Xopen
4399  let qfbnum = bufnr('')
4400  Xclose
4401  " Even after the quickfix window is closed, the buffer should be loaded
4402  call assert_true(bufloaded(qfbnum))
4403  call assert_true(qfbnum, g:Xgetlist({'qfbufnr' : 0}).qfbufnr)
4404  Xopen
4405  " Buffer should be reused when opening the window again
4406  call assert_equal(qfbnum, bufnr(''))
4407  Xclose
4408
4409  if a:cchar == 'l'
4410    %bwipe
4411    " For a location list, when both the file window and the location list
4412    " window for the list are closed, then the buffer should be freed.
4413    new | only
4414    lexpr "F1:10:Line10"
4415    let wid = win_getid()
4416    lopen
4417    let qfbnum = bufnr('')
4418    call assert_match(qfbnum . ' %a-  "\[Location List]"', execute('ls'))
4419    close
4420    " When the location list window is closed, the buffer name should not
4421    " change to 'Quickfix List'
4422    call assert_match(qfbnum . 'u h-  "\[Location List]"', execute('ls!'))
4423    call assert_true(bufloaded(qfbnum))
4424
4425    " After deleting a location list buffer using ":bdelete", opening the
4426    " location list window should mark the buffer as a location list buffer.
4427    exe "bdelete " . qfbnum
4428    lopen
4429    call assert_equal("quickfix", &buftype)
4430    call assert_equal(1, getwininfo(win_getid(winnr()))[0].loclist)
4431    call assert_equal(wid, getloclist(0, {'filewinid' : 0}).filewinid)
4432    call assert_false(&swapfile)
4433    lclose
4434
4435    " When the location list is cleared for the window, the buffer should be
4436    " removed
4437    call setloclist(0, [], 'f')
4438    call assert_false(bufexists(qfbnum))
4439    call assert_equal(0, getloclist(0, {'qfbufnr' : 0}).qfbufnr)
4440
4441    " When the location list is freed with the location list window open, the
4442    " location list buffer should not be lost. It should be reused when the
4443    " location list is again populated.
4444    lexpr "F1:10:Line10"
4445    lopen
4446    let wid = win_getid()
4447    let qfbnum = bufnr('')
4448    wincmd p
4449    call setloclist(0, [], 'f')
4450    lexpr "F1:10:Line10"
4451    lopen
4452    call assert_equal(wid, win_getid())
4453    call assert_equal(qfbnum, bufnr(''))
4454    lclose
4455
4456    " When the window with the location list is closed, the buffer should be
4457    " removed
4458    new | only
4459    call assert_false(bufexists(qfbnum))
4460  endif
4461endfunc
4462
4463func Test_qfbuf()
4464  call Xqfbuf_test('c')
4465  call Xqfbuf_test('l')
4466endfunc
4467
4468" If there is an autocmd to use only one window, then opening the location
4469" list window used to crash Vim.
4470func Test_winonly_autocmd()
4471  call s:create_test_file('Xtest1')
4472  " Autocmd to show only one Vim window at a time
4473  autocmd WinEnter * only
4474  new
4475  " Load the location list
4476  lexpr "Xtest1:5:Line5\nXtest1:10:Line10\nXtest1:15:Line15"
4477  let loclistid = getloclist(0, {'id' : 0}).id
4478  " Open the location list window. Only this window will be shown and the file
4479  " window is closed.
4480  lopen
4481  call assert_equal(loclistid, getloclist(0, {'id' : 0}).id)
4482  " Jump to an entry in the location list and make sure that the cursor is
4483  " positioned correctly.
4484  ll 3
4485  call assert_equal(loclistid, getloclist(0, {'id' : 0}).id)
4486  call assert_equal('Xtest1', @%)
4487  call assert_equal(15, line('.'))
4488  " Cleanup
4489  autocmd! WinEnter
4490  new | only
4491  call delete('Xtest1')
4492endfunc
4493
4494" Test to make sure that an empty quickfix buffer is not reused for loading
4495" a normal buffer.
4496func Test_empty_qfbuf()
4497  enew | only
4498  call writefile(["Test"], 'Xfile1')
4499  call setqflist([], 'f')
4500  copen | only
4501  let qfbuf = bufnr('')
4502  edit Xfile1
4503  call assert_notequal(qfbuf, bufnr(''))
4504  enew
4505  call delete('Xfile1')
4506endfunc
4507
4508" Test for the :cbelow, :cabove, :lbelow and :labove commands.
4509" And for the :cafter, :cbefore, :lafter and :lbefore commands.
4510func Xtest_below(cchar)
4511  call s:setup_commands(a:cchar)
4512
4513  " No quickfix/location list
4514  call assert_fails('Xbelow', 'E42:')
4515  call assert_fails('Xabove', 'E42:')
4516  call assert_fails('Xbefore', 'E42:')
4517  call assert_fails('Xafter', 'E42:')
4518
4519  " Empty quickfix/location list
4520  call g:Xsetlist([])
4521  call assert_fails('Xbelow', 'E42:')
4522  call assert_fails('Xabove', 'E42:')
4523  call assert_fails('Xbefore', 'E42:')
4524  call assert_fails('Xafter', 'E42:')
4525
4526  call s:create_test_file('X1')
4527  call s:create_test_file('X2')
4528  call s:create_test_file('X3')
4529  call s:create_test_file('X4')
4530
4531  " Invalid entries
4532  edit X1
4533  call g:Xsetlist(["E1", "E2"])
4534  call assert_fails('Xbelow', 'E42:')
4535  call assert_fails('Xabove', 'E42:')
4536  call assert_fails('3Xbelow', 'E42:')
4537  call assert_fails('4Xabove', 'E42:')
4538  call assert_fails('Xbefore', 'E42:')
4539  call assert_fails('Xafter', 'E42:')
4540  call assert_fails('3Xbefore', 'E42:')
4541  call assert_fails('4Xafter', 'E42:')
4542
4543  " Test the commands with various arguments
4544  Xexpr ["X1:5:3:L5", "X2:5:2:L5", "X2:10:3:L10", "X2:15:4:L15", "X3:3:5:L3"]
4545  edit +7 X2
4546  Xabove
4547  call assert_equal(['X2', 5], [@%, line('.')])
4548  call assert_fails('Xabove', 'E553:')
4549  normal 7G
4550  Xbefore
4551  call assert_equal(['X2', 5, 2], [@%, line('.'), col('.')])
4552  call assert_fails('Xbefore', 'E553:')
4553
4554  normal 2j
4555  Xbelow
4556  call assert_equal(['X2', 10], [@%, line('.')])
4557  normal 7G
4558  Xafter
4559  call assert_equal(['X2', 10, 3], [@%, line('.'), col('.')])
4560
4561  " Last error in this file
4562  Xbelow 99
4563  call assert_equal(['X2', 15], [@%, line('.')])
4564  call assert_fails('Xbelow', 'E553:')
4565  normal gg
4566  Xafter 99
4567  call assert_equal(['X2', 15, 4], [@%, line('.'), col('.')])
4568  call assert_fails('Xafter', 'E553:')
4569
4570  " First error in this file
4571  Xabove 99
4572  call assert_equal(['X2', 5], [@%, line('.')])
4573  call assert_fails('Xabove', 'E553:')
4574  normal G
4575  Xbefore 99
4576  call assert_equal(['X2', 5, 2], [@%, line('.'), col('.')])
4577  call assert_fails('Xbefore', 'E553:')
4578
4579  normal gg
4580  Xbelow 2
4581  call assert_equal(['X2', 10], [@%, line('.')])
4582  normal gg
4583  Xafter 2
4584  call assert_equal(['X2', 10, 3], [@%, line('.'), col('.')])
4585
4586  normal G
4587  Xabove 2
4588  call assert_equal(['X2', 10], [@%, line('.')])
4589  normal G
4590  Xbefore 2
4591  call assert_equal(['X2', 10, 3], [@%, line('.'), col('.')])
4592
4593  edit X4
4594  call assert_fails('Xabove', 'E42:')
4595  call assert_fails('Xbelow', 'E42:')
4596  call assert_fails('Xbefore', 'E42:')
4597  call assert_fails('Xafter', 'E42:')
4598  if a:cchar == 'l'
4599    " If a buffer has location list entries from some other window but not
4600    " from the current window, then the commands should fail.
4601    edit X1 | split | call setloclist(0, [], 'f')
4602    call assert_fails('Xabove', 'E776:')
4603    call assert_fails('Xbelow', 'E776:')
4604    call assert_fails('Xbefore', 'E776:')
4605    call assert_fails('Xafter', 'E776:')
4606    close
4607  endif
4608
4609  " Test for lines with multiple quickfix entries
4610  Xexpr ["X1:5:L5", "X2:5:1:L5_1", "X2:5:2:L5_2", "X2:5:3:L5_3",
4611	      \ "X2:10:1:L10_1", "X2:10:2:L10_2", "X2:10:3:L10_3",
4612	      \ "X2:15:1:L15_1", "X2:15:2:L15_2", "X2:15:3:L15_3", "X3:3:L3"]
4613  edit +1 X2
4614  Xbelow 2
4615  call assert_equal(['X2', 10, 1], [@%, line('.'), col('.')])
4616  normal 1G
4617  Xafter 2
4618  call assert_equal(['X2', 5, 2], [@%, line('.'), col('.')])
4619
4620  normal gg
4621  Xbelow 99
4622  call assert_equal(['X2', 15, 1], [@%, line('.'), col('.')])
4623  normal gg
4624  Xafter 99
4625  call assert_equal(['X2', 15, 3], [@%, line('.'), col('.')])
4626
4627  normal G
4628  Xabove 2
4629  call assert_equal(['X2', 10, 1], [@%, line('.'), col('.')])
4630  normal G
4631  Xbefore 2
4632  call assert_equal(['X2', 15, 2], [@%, line('.'), col('.')])
4633
4634  normal G
4635  Xabove 99
4636  call assert_equal(['X2', 5, 1], [@%, line('.'), col('.')])
4637  normal G
4638  Xbefore 99
4639  call assert_equal(['X2', 5, 1], [@%, line('.'), col('.')])
4640
4641  normal 10G
4642  Xabove
4643  call assert_equal(['X2', 5, 1], [@%, line('.'), col('.')])
4644  normal 10G$
4645  2Xbefore
4646  call assert_equal(['X2', 10, 2], [@%, line('.'), col('.')])
4647
4648  normal 10G
4649  Xbelow
4650  call assert_equal(['X2', 15, 1], [@%, line('.'), col('.')])
4651  normal 9G
4652  5Xafter
4653  call assert_equal(['X2', 15, 2], [@%, line('.'), col('.')])
4654
4655  " Invalid range
4656  if a:cchar == 'c'
4657    call assert_fails('-2cbelow', 'E16:')
4658    call assert_fails('-2cafter', 'E16:')
4659  else
4660    call assert_fails('-2lbelow', 'E16:')
4661    call assert_fails('-2lafter', 'E16:')
4662  endif
4663
4664  call delete('X1')
4665  call delete('X2')
4666  call delete('X3')
4667  call delete('X4')
4668endfunc
4669
4670func Test_cbelow()
4671  call Xtest_below('c')
4672  call Xtest_below('l')
4673endfunc
4674
4675func Test_quickfix_count()
4676  let commands = [
4677	\ 'cNext',
4678	\ 'cNfile',
4679	\ 'cabove',
4680	\ 'cbelow',
4681	\ 'cfirst',
4682	\ 'clast',
4683	\ 'cnewer',
4684	\ 'cnext',
4685	\ 'cnfile',
4686	\ 'colder',
4687	\ 'cprevious',
4688	\ 'crewind',
4689	\
4690	\ 'lNext',
4691	\ 'lNfile',
4692	\ 'labove',
4693	\ 'lbelow',
4694	\ 'lfirst',
4695	\ 'llast',
4696	\ 'lnewer',
4697	\ 'lnext',
4698	\ 'lnfile',
4699	\ 'lolder',
4700	\ 'lprevious',
4701	\ 'lrewind',
4702	\ ]
4703  for cmd in commands
4704    call assert_fails('-1' .. cmd, 'E16:')
4705    call assert_fails('.' .. cmd, 'E16:')
4706    call assert_fails('%' .. cmd, 'E16:')
4707    call assert_fails('$' .. cmd, 'E16:')
4708  endfor
4709endfunc
4710
4711" Test for aborting quickfix commands using QuickFixCmdPre
4712func Xtest_qfcmd_abort(cchar)
4713  call s:setup_commands(a:cchar)
4714
4715  call g:Xsetlist([], 'f')
4716
4717  " cexpr/lexpr
4718  let e = ''
4719  try
4720    Xexpr ["F1:10:Line10", "F2:20:Line20"]
4721  catch /.*/
4722    let e = v:exception
4723  endtry
4724  call assert_equal('AbortCmd', e)
4725  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4726
4727  " cfile/lfile
4728  call writefile(["F1:10:Line10", "F2:20:Line20"], 'Xfile1')
4729  let e = ''
4730  try
4731    Xfile Xfile1
4732  catch /.*/
4733    let e = v:exception
4734  endtry
4735  call assert_equal('AbortCmd', e)
4736  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4737  call delete('Xfile1')
4738
4739  " cgetbuffer/lgetbuffer
4740  enew!
4741  call append(0, ["F1:10:Line10", "F2:20:Line20"])
4742  let e = ''
4743  try
4744    Xgetbuffer
4745  catch /.*/
4746    let e = v:exception
4747  endtry
4748  call assert_equal('AbortCmd', e)
4749  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4750  enew!
4751
4752  " vimgrep/lvimgrep
4753  let e = ''
4754  try
4755    Xvimgrep /func/ test_quickfix.vim
4756  catch /.*/
4757    let e = v:exception
4758  endtry
4759  call assert_equal('AbortCmd', e)
4760  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4761
4762  " helpgrep/lhelpgrep
4763  let e = ''
4764  try
4765    Xhelpgrep quickfix
4766  catch /.*/
4767    let e = v:exception
4768  endtry
4769  call assert_equal('AbortCmd', e)
4770  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4771
4772  " grep/lgrep
4773  if has('unix')
4774    let e = ''
4775    try
4776      silent Xgrep func test_quickfix.vim
4777    catch /.*/
4778      let e = v:exception
4779    endtry
4780    call assert_equal('AbortCmd', e)
4781    call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4782  endif
4783endfunc
4784
4785func Test_qfcmd_abort()
4786  augroup QF_Test
4787    au!
4788    autocmd  QuickFixCmdPre * throw "AbortCmd"
4789  augroup END
4790
4791  call Xtest_qfcmd_abort('c')
4792  call Xtest_qfcmd_abort('l')
4793
4794  augroup QF_Test
4795    au!
4796  augroup END
4797endfunc
4798
4799" Test for using a file in one of the parent directories.
4800func Test_search_in_dirstack()
4801  call mkdir('Xtestdir/a/b/c', 'p')
4802  let save_cwd = getcwd()
4803  call writefile(["X1_L1", "X1_L2"], 'Xtestdir/Xfile1')
4804  call writefile(["X2_L1", "X2_L2"], 'Xtestdir/a/Xfile2')
4805  call writefile(["X3_L1", "X3_L2"], 'Xtestdir/a/b/Xfile3')
4806  call writefile(["X4_L1", "X4_L2"], 'Xtestdir/a/b/c/Xfile4')
4807
4808  let lines = "Entering dir Xtestdir\n" .
4809	      \ "Entering dir a\n" .
4810	      \ "Entering dir b\n" .
4811	      \ "Xfile2:2:X2_L2\n" .
4812	      \ "Leaving dir a\n" .
4813	      \ "Xfile1:2:X1_L2\n" .
4814	      \ "Xfile3:1:X3_L1\n" .
4815	      \ "Entering dir c\n" .
4816	      \ "Xfile4:2:X4_L2\n" .
4817	      \ "Leaving dir c\n"
4818  set efm=%DEntering\ dir\ %f,%XLeaving\ dir\ %f,%f:%l:%m
4819  cexpr lines .. "Leaving dir Xtestdir|\n" | let next = 1
4820  call assert_equal(11, getqflist({'size' : 0}).size)
4821  call assert_equal(4, getqflist({'idx' : 0}).idx)
4822  call assert_equal('X2_L2', getline('.'))
4823  call assert_equal(1, next)
4824  cnext
4825  call assert_equal(6, getqflist({'idx' : 0}).idx)
4826  call assert_equal('X1_L2', getline('.'))
4827  cnext
4828  call assert_equal(7, getqflist({'idx' : 0}).idx)
4829  call assert_equal(1, line('$'))
4830  call assert_equal('', getline(1))
4831  cnext
4832  call assert_equal(9, getqflist({'idx' : 0}).idx)
4833  call assert_equal(1, line('$'))
4834  call assert_equal('', getline(1))
4835
4836  set efm&
4837  exe 'cd ' . save_cwd
4838  call delete('Xtestdir', 'rf')
4839endfunc
4840
4841" Test for :cquit
4842func Test_cquit()
4843  " Exit Vim with a non-zero value
4844  if RunVim([], ["cquit 7"], '')
4845    call assert_equal(7, v:shell_error)
4846  endif
4847
4848  if RunVim([], ["50cquit"], '')
4849    call assert_equal(50, v:shell_error)
4850  endif
4851
4852  " Exit Vim with default value
4853  if RunVim([], ["cquit"], '')
4854    call assert_equal(1, v:shell_error)
4855  endif
4856
4857  " Exit Vim with zero value
4858  if RunVim([], ["cquit 0"], '')
4859    call assert_equal(0, v:shell_error)
4860  endif
4861
4862  " Exit Vim with negative value
4863  call assert_fails('-3cquit', 'E16:')
4864endfunc
4865
4866" Test for getting a specific item from a quickfix list
4867func Xtest_getqflist_by_idx(cchar)
4868  call s:setup_commands(a:cchar)
4869  " Empty list
4870  call assert_equal([], g:Xgetlist({'idx' : 1, 'items' : 0}).items)
4871  Xexpr ['F1:10:L10', 'F1:20:L20']
4872  let l = g:Xgetlist({'idx' : 2, 'items' : 0}).items
4873  call assert_equal(bufnr('F1'), l[0].bufnr)
4874  call assert_equal(20, l[0].lnum)
4875  call assert_equal('L20', l[0].text)
4876  call assert_equal([], g:Xgetlist({'idx' : -1, 'items' : 0}).items)
4877  call assert_equal([], g:Xgetlist({'idx' : 3, 'items' : 0}).items)
4878  %bwipe!
4879endfunc
4880
4881func Test_getqflist_by_idx()
4882  call Xtest_getqflist_by_idx('c')
4883  call Xtest_getqflist_by_idx('l')
4884endfunc
4885
4886" Test for the 'quickfixtextfunc' setting
4887func Tqfexpr(info)
4888  if a:info.quickfix
4889    let qfl = getqflist({'id' : a:info.id, 'items' : 1}).items
4890  else
4891    let qfl = getloclist(a:info.winid, {'id' : a:info.id, 'items' : 1}).items
4892  endif
4893
4894  let l = []
4895  for idx in range(a:info.start_idx - 1, a:info.end_idx - 1)
4896    let e = qfl[idx]
4897    let s = ''
4898    if e.bufnr != 0
4899      let bname = bufname(e.bufnr)
4900      let s ..= fnamemodify(bname, ':.')
4901    endif
4902    let s ..= '-'
4903    let s ..= 'L' .. string(e.lnum) .. 'C' .. string(e.col) .. '-'
4904    let s ..= e.text
4905    call add(l, s)
4906  endfor
4907
4908  return l
4909endfunc
4910
4911func Xtest_qftextfunc(cchar)
4912  call s:setup_commands(a:cchar)
4913
4914  set efm=%f:%l:%c:%m
4915  set quickfixtextfunc=Tqfexpr
4916  call assert_equal('Tqfexpr', &quickfixtextfunc)
4917  call assert_equal('',
4918        \ g:Xgetlist({'quickfixtextfunc' : 1}).quickfixtextfunc)
4919  Xexpr ['F1:10:2:green', 'F1:20:4:blue']
4920  Xwindow
4921  call assert_equal('F1-L10C2-green', getline(1))
4922  call assert_equal('F1-L20C4-blue', getline(2))
4923  Xclose
4924  set quickfixtextfunc&vim
4925  Xwindow
4926  call assert_equal('F1|10 col 2| green', getline(1))
4927  call assert_equal('F1|20 col 4| blue', getline(2))
4928  Xclose
4929  set efm&
4930  set quickfixtextfunc&
4931
4932  " Test for per list 'quickfixtextfunc' setting
4933  func PerQfText(info)
4934    if a:info.quickfix
4935      let qfl = getqflist({'id' : a:info.id, 'items' : 1}).items
4936    else
4937      let qfl = getloclist(a:info.winid, {'id' : a:info.id, 'items' : 1}).items
4938    endif
4939    if empty(qfl)
4940      return []
4941    endif
4942    let l = []
4943    for idx in range(a:info.start_idx - 1, a:info.end_idx - 1)
4944      call add(l, 'Line ' .. qfl[idx].lnum .. ', Col ' .. qfl[idx].col)
4945    endfor
4946    return l
4947  endfunc
4948  set quickfixtextfunc=Tqfexpr
4949  call g:Xsetlist([], ' ', {'quickfixtextfunc' : "PerQfText"})
4950  Xaddexpr ['F1:10:2:green', 'F1:20:4:blue']
4951  Xwindow
4952  call assert_equal('Line 10, Col 2', getline(1))
4953  call assert_equal('Line 20, Col 4', getline(2))
4954  Xclose
4955  call assert_equal(function('PerQfText'),
4956        \ g:Xgetlist({'quickfixtextfunc' : 1}).quickfixtextfunc)
4957  " Add entries to the list when the quickfix buffer is hidden
4958  Xaddexpr ['F1:30:6:red']
4959  Xwindow
4960  call assert_equal('Line 30, Col 6', getline(3))
4961  Xclose
4962  call g:Xsetlist([], 'r', {'quickfixtextfunc' : ''})
4963  call assert_equal('', g:Xgetlist({'quickfixtextfunc' : 1}).quickfixtextfunc)
4964  set quickfixtextfunc&
4965  delfunc PerQfText
4966
4967  " Non-existing function
4968  set quickfixtextfunc=Tabc
4969  call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue']", 'E117:')
4970  call assert_fails("Xwindow", 'E117:')
4971  Xclose
4972  set quickfixtextfunc&
4973
4974  " set option to a non-function
4975  set quickfixtextfunc=[10,\ 20]
4976  call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue']", 'E117:')
4977  call assert_fails("Xwindow", 'E117:')
4978  Xclose
4979  set quickfixtextfunc&
4980
4981  " set option to a function with different set of arguments
4982  func Xqftext(a, b, c)
4983    return a:a .. a:b .. a:c
4984  endfunc
4985  set quickfixtextfunc=Xqftext
4986  call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue']", 'E119:')
4987  call assert_fails("Xwindow", 'E119:')
4988  Xclose
4989
4990  " set option to a function that returns a list with non-strings
4991  func Xqftext2(d)
4992    return ['one', [], 'two']
4993  endfunc
4994  set quickfixtextfunc=Xqftext2
4995  call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue', 'F1:30:6:red']",
4996                                                                  \ 'E730:')
4997  call assert_fails('Xwindow', 'E730:')
4998  call assert_equal(['one', 'F1|20 col 4| blue', 'F1|30 col 6| red'],
4999        \ getline(1, '$'))
5000  Xclose
5001
5002  set quickfixtextfunc&
5003  delfunc Xqftext
5004  delfunc Xqftext2
5005
5006  " set the global option to a lambda function
5007  set quickfixtextfunc={d\ ->\ map(g:Xgetlist({'id'\ :\ d.id,\ 'items'\ :\ 1}).items[d.start_idx-1:d.end_idx-1],\ 'v:val.text')}
5008  Xexpr ['F1:10:2:green', 'F1:20:4:blue']
5009  Xwindow
5010  call assert_equal(['green', 'blue'], getline(1, '$'))
5011  Xclose
5012  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)
5013  set quickfixtextfunc&
5014
5015  " use a lambda function that returns an empty list
5016  set quickfixtextfunc={d\ ->\ []}
5017  Xexpr ['F1:10:2:green', 'F1:20:4:blue']
5018  Xwindow
5019  call assert_equal(['F1|10 col 2| green', 'F1|20 col 4| blue'],
5020        \ getline(1, '$'))
5021  Xclose
5022  set quickfixtextfunc&
5023
5024  " use a lambda function that returns a list with empty strings
5025  set quickfixtextfunc={d\ ->\ ['',\ '']}
5026  Xexpr ['F1:10:2:green', 'F1:20:4:blue']
5027  Xwindow
5028  call assert_equal(['F1|10 col 2| green', 'F1|20 col 4| blue'],
5029        \ getline(1, '$'))
5030  Xclose
5031  set quickfixtextfunc&
5032
5033  " set the per-quickfix list text function to a lambda function
5034  call g:Xsetlist([], ' ',
5035        \ {'quickfixtextfunc' :
5036        \   {d -> map(g:Xgetlist({'id' : d.id, 'items' : 1}).items[d.start_idx-1:d.end_idx-1],
5037        \ "'Line ' .. v:val.lnum .. ', Col ' .. v:val.col")}})
5038  Xaddexpr ['F1:10:2:green', 'F1:20:4:blue']
5039  Xwindow
5040  call assert_equal('Line 10, Col 2', getline(1))
5041  call assert_equal('Line 20, Col 4', getline(2))
5042  Xclose
5043  call assert_match("function('<lambda>\\d\\+')", string(g:Xgetlist({'quickfixtextfunc' : 1}).quickfixtextfunc))
5044  call g:Xsetlist([], 'f')
5045endfunc
5046
5047func Test_qftextfunc()
5048  call Xtest_qftextfunc('c')
5049  call Xtest_qftextfunc('l')
5050endfunc
5051
5052" Running :lhelpgrep command more than once in a help window, doesn't jump to
5053" the help topic
5054func Test_lhelpgrep_from_help_window()
5055  call mkdir('Xtestdir/doc', 'p')
5056  call writefile(['window'], 'Xtestdir/doc/a.txt')
5057  call writefile(['buffer'], 'Xtestdir/doc/b.txt')
5058  let save_rtp = &rtp
5059  let &rtp = 'Xtestdir'
5060  lhelpgrep window
5061  lhelpgrep buffer
5062  call assert_equal('b.txt', fnamemodify(@%, ":p:t"))
5063  lhelpgrep window
5064  call assert_equal('a.txt', fnamemodify(@%, ":p:t"))
5065  let &rtp = save_rtp
5066  call delete('Xtestdir', 'rf')
5067  new | only!
5068endfunc
5069
5070" Test for the crash fixed by 7.3.715
5071func Test_setloclist_crash()
5072  %bw!
5073  let g:BufNum = bufnr()
5074  augroup QF_Test
5075    au!
5076    au BufUnload * call setloclist(0, [{'bufnr':g:BufNum, 'lnum':1, 'col':1, 'text': 'tango down'}])
5077  augroup END
5078
5079  try
5080    lvimgrep /.*/ *.mak
5081  catch /E926:/
5082  endtry
5083  call assert_equal('tango down', getloclist(0, {'items' : 0}).items[0].text)
5084  call assert_equal(1, getloclist(0, {'size' : 0}).size)
5085
5086  augroup QF_Test
5087    au!
5088  augroup END
5089  unlet g:BufNum
5090  %bw!
5091endfunc
5092
5093" vim: shiftwidth=2 sts=2 expandtab
5094