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