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		  \ 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},
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,
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		\ g:Xgetlist({'id' : qfid, 'all' : 0}))
3545  endif
3546
3547  " Non-existing quickfix list number
3548  call assert_equal('', g:Xgetlist({'nr' : 5, 'context' : 0}).context)
3549  call assert_equal(0, g:Xgetlist({'nr' : 5}).nr)
3550  call assert_equal(0, g:Xgetlist({'nr' : 5, 'idx' : 0}).idx)
3551  call assert_equal([], g:Xgetlist({'nr' : 5, 'items' : 0}).items)
3552  call assert_equal(0, g:Xgetlist({'nr' : 5, 'id' : 0}).id)
3553  call assert_equal(0, g:Xgetlist({'nr' : 5, 'size' : 0}).size)
3554  call assert_equal('', g:Xgetlist({'nr' : 5, 'title' : 0}).title)
3555  call assert_equal(0, g:Xgetlist({'nr' : 5, 'winid' : 0}).winid)
3556  call assert_equal(0, g:Xgetlist({'nr' : 5, 'changedtick' : 0}).changedtick)
3557  if a:cchar == 'c'
3558    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
3559		\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
3560		\ 'changedtick' : 0, 'qfbufnr' : qfbufnr},
3561		\ g:Xgetlist({'nr' : 5, 'all' : 0}))
3562  else
3563    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
3564		\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
3565		\ 'changedtick' : 0, 'filewinid' : 0, 'qfbufnr' : 0},
3566		\ g:Xgetlist({'nr' : 5, 'all' : 0}))
3567  endif
3568endfunc
3569
3570func Test_getqflist()
3571  call Xgetlist_empty_tests('c')
3572  call Xgetlist_empty_tests('l')
3573endfunc
3574
3575func Test_getqflist_invalid_nr()
3576  " The following commands used to crash Vim
3577  cexpr ""
3578  call getqflist({'nr' : $XXX_DOES_NOT_EXIST_XXX})
3579
3580  " Cleanup
3581  call setqflist([], 'r')
3582endfunc
3583
3584" Tests for the quickfix/location list changedtick
3585func Xqftick_tests(cchar)
3586  call s:setup_commands(a:cchar)
3587
3588  call g:Xsetlist([], 'f')
3589
3590  Xexpr "F1:10:Line10"
3591  let qfid = g:Xgetlist({'id' : 0}).id
3592  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3593  Xaddexpr "F2:20:Line20\nF2:21:Line21"
3594  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
3595  call g:Xsetlist([], 'a', {'lines' : ["F3:30:Line30", "F3:31:Line31"]})
3596  call assert_equal(3, g:Xgetlist({'changedtick' : 0}).changedtick)
3597  call g:Xsetlist([], 'r', {'lines' : ["F4:40:Line40"]})
3598  call assert_equal(4, g:Xgetlist({'changedtick' : 0}).changedtick)
3599  call g:Xsetlist([], 'a', {'title' : 'New Title'})
3600  call assert_equal(5, g:Xgetlist({'changedtick' : 0}).changedtick)
3601
3602  enew!
3603  call append(0, ["F5:50:L50", "F6:60:L60"])
3604  Xaddbuffer
3605  call assert_equal(6, g:Xgetlist({'changedtick' : 0}).changedtick)
3606  enew!
3607
3608  call g:Xsetlist([], 'a', {'context' : {'bus' : 'pci'}})
3609  call assert_equal(7, g:Xgetlist({'changedtick' : 0}).changedtick)
3610  call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'},
3611	      \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], 'a')
3612  call assert_equal(8, g:Xgetlist({'changedtick' : 0}).changedtick)
3613  call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'},
3614	      \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], ' ')
3615  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3616  call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'},
3617	      \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], 'r')
3618  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
3619
3620  call writefile(["F8:80:L80", "F8:81:L81"], "Xone")
3621  Xfile Xone
3622  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3623  Xaddfile Xone
3624  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
3625
3626  " Test case for updating a non-current quickfix list
3627  call g:Xsetlist([], 'f')
3628  Xexpr "F1:1:L1"
3629  Xexpr "F2:2:L2"
3630  call g:Xsetlist([], 'a', {'nr' : 1, "lines" : ["F10:10:L10"]})
3631  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3632  call assert_equal(2, g:Xgetlist({'nr' : 1, 'changedtick' : 0}).changedtick)
3633
3634  call delete("Xone")
3635endfunc
3636
3637func Test_qf_tick()
3638  call Xqftick_tests('c')
3639  call Xqftick_tests('l')
3640endfunc
3641
3642" Test helpgrep with lang specifier
3643func Xtest_helpgrep_with_lang_specifier(cchar)
3644  call s:setup_commands(a:cchar)
3645  Xhelpgrep Vim@en
3646  call assert_equal('help', &filetype)
3647  call assert_notequal(0, g:Xgetlist({'nr' : '$'}).nr)
3648  new | only
3649endfunc
3650
3651func Test_helpgrep_with_lang_specifier()
3652  call Xtest_helpgrep_with_lang_specifier('c')
3653  call Xtest_helpgrep_with_lang_specifier('l')
3654endfunc
3655
3656" The following test used to crash Vim.
3657" Open the location list window and close the regular window associated with
3658" the location list. When the garbage collection runs now, it incorrectly
3659" marks the location list context as not in use and frees the context.
3660func Test_ll_window_ctx()
3661  call setloclist(0, [], 'f')
3662  call setloclist(0, [], 'a', {'context' : []})
3663  lopen | only
3664  call test_garbagecollect_now()
3665  echo getloclist(0, {'context' : 1}).context
3666  enew | only
3667endfunc
3668
3669" The following test used to crash vim
3670func Test_lfile_crash()
3671  sp Xtest
3672  au QuickFixCmdPre * bw
3673  call assert_fails('lfile', 'E40')
3674  au! QuickFixCmdPre
3675endfunc
3676
3677" The following test used to crash vim
3678func Test_lbuffer_crash()
3679  sv Xtest
3680  augroup QF_Test
3681    au!
3682    au * * bw
3683  augroup END
3684  lbuffer
3685  augroup QF_Test
3686    au!
3687  augroup END
3688endfunc
3689
3690" The following test used to crash vim
3691func Test_lexpr_crash()
3692  augroup QF_Test
3693    au!
3694    au * * call setloclist(0, [], 'f')
3695  augroup END
3696  lexpr ""
3697  augroup QF_Test
3698    au!
3699  augroup END
3700
3701  enew | only
3702  augroup QF_Test
3703    au!
3704    au BufNew * call setloclist(0, [], 'f')
3705  augroup END
3706  lexpr 'x:1:x'
3707  augroup QF_Test
3708    au!
3709  augroup END
3710
3711  enew | only
3712  lexpr ''
3713  lopen
3714  augroup QF_Test
3715    au!
3716    au FileType * call setloclist(0, [], 'f')
3717  augroup END
3718  lexpr ''
3719  augroup QF_Test
3720    au!
3721  augroup END
3722endfunc
3723
3724" The following test used to crash Vim
3725func Test_lvimgrep_crash()
3726  sv Xtest
3727  augroup QF_Test
3728    au!
3729    au * * call setloclist(0, [], 'f')
3730  augroup END
3731  lvimgrep quickfix test_quickfix.vim
3732  augroup QF_Test
3733    au!
3734  augroup END
3735
3736  new | only
3737  augroup QF_Test
3738    au!
3739    au BufEnter * call setloclist(0, [], 'r')
3740  augroup END
3741  call assert_fails('lvimgrep Test_lvimgrep_crash *', 'E926:')
3742  augroup QF_Test
3743    au!
3744  augroup END
3745
3746  enew | only
3747endfunc
3748
3749func Test_lvimgrep_crash2()
3750  au BufNewFile x sfind
3751  call assert_fails('lvimgrep x x', 'E471:')
3752  call assert_fails('lvimgrep x x x', 'E471:')
3753
3754  au! BufNewFile
3755endfunc
3756
3757" Test for the position of the quickfix and location list window
3758func Test_qfwin_pos()
3759  " Open two windows
3760  new | only
3761  new
3762  cexpr ['F1:10:L10']
3763  copen
3764  " Quickfix window should be the bottom most window
3765  call assert_equal(3, winnr())
3766  close
3767  " Open at the very top
3768  wincmd t
3769  topleft copen
3770  call assert_equal(1, winnr())
3771  close
3772  " open left of the current window
3773  wincmd t
3774  below new
3775  leftabove copen
3776  call assert_equal(2, winnr())
3777  close
3778  " open right of the current window
3779  rightbelow copen
3780  call assert_equal(3, winnr())
3781  close
3782endfunc
3783
3784" Tests for quickfix/location lists changed by autocommands when
3785" :vimgrep/:lvimgrep commands are running.
3786func Test_vimgrep_autocmd()
3787  call setqflist([], 'f')
3788  call writefile(['stars'], 'Xtest1.txt')
3789  call writefile(['stars'], 'Xtest2.txt')
3790
3791  " Test 1:
3792  " When searching for a pattern using :vimgrep, if the quickfix list is
3793  " changed by an autocmd, the results should be added to the correct quickfix
3794  " list.
3795  autocmd BufRead Xtest2.txt cexpr '' | cexpr ''
3796  silent vimgrep stars Xtest*.txt
3797  call assert_equal(1, getqflist({'nr' : 0}).nr)
3798  call assert_equal(3, getqflist({'nr' : '$'}).nr)
3799  call assert_equal('Xtest2.txt', bufname(getqflist()[1].bufnr))
3800  au! BufRead Xtest2.txt
3801
3802  " Test 2:
3803  " When searching for a pattern using :vimgrep, if the quickfix list is
3804  " freed, then a error should be given.
3805  silent! %bwipe!
3806  call setqflist([], 'f')
3807  autocmd BufRead Xtest2.txt for i in range(10) | cexpr '' | endfor
3808  call assert_fails('vimgrep stars Xtest*.txt', 'E925:')
3809  au! BufRead Xtest2.txt
3810
3811  " Test 3:
3812  " When searching for a pattern using :lvimgrep, if the location list is
3813  " freed, then the command should error out.
3814  silent! %bwipe!
3815  let g:save_winid = win_getid()
3816  autocmd BufRead Xtest2.txt call setloclist(g:save_winid, [], 'f')
3817  call assert_fails('lvimgrep stars Xtest*.txt', 'E926:')
3818  au! BufRead Xtest2.txt
3819
3820  call delete('Xtest1.txt')
3821  call delete('Xtest2.txt')
3822  call setqflist([], 'f')
3823endfunc
3824
3825" Test for an autocmd changing the current directory when running vimgrep
3826func Xvimgrep_autocmd_cd(cchar)
3827  call s:setup_commands(a:cchar)
3828
3829  %bwipe
3830  let save_cwd = getcwd()
3831
3832  augroup QF_Test
3833    au!
3834    autocmd BufRead * silent cd %:p:h
3835  augroup END
3836
3837  10Xvimgrep /vim/ Xdir/**
3838  let l = g:Xgetlist()
3839  call assert_equal('f1.txt', bufname(l[0].bufnr))
3840  call assert_equal('f2.txt', fnamemodify(bufname(l[2].bufnr), ':t'))
3841
3842  augroup QF_Test
3843    au!
3844  augroup END
3845
3846  exe 'cd ' . save_cwd
3847endfunc
3848
3849func Test_vimgrep_autocmd_cd()
3850  call mkdir('Xdir/a', 'p')
3851  call mkdir('Xdir/b', 'p')
3852  call writefile(['a_L1_vim', 'a_L2_vim'], 'Xdir/a/f1.txt')
3853  call writefile(['b_L1_vim', 'b_L2_vim'], 'Xdir/b/f2.txt')
3854  call Xvimgrep_autocmd_cd('c')
3855  call Xvimgrep_autocmd_cd('l')
3856  %bwipe
3857  call delete('Xdir', 'rf')
3858endfunc
3859
3860" The following test used to crash Vim
3861func Test_lhelpgrep_autocmd()
3862  lhelpgrep quickfix
3863  autocmd QuickFixCmdPost * call setloclist(0, [], 'f')
3864  lhelpgrep buffer
3865  call assert_equal('help', &filetype)
3866  call assert_equal(0, getloclist(0, {'nr' : '$'}).nr)
3867  lhelpgrep tabpage
3868  call assert_equal('help', &filetype)
3869  call assert_equal(1, getloclist(0, {'nr' : '$'}).nr)
3870  au! QuickFixCmdPost
3871
3872  new | only
3873  augroup QF_Test
3874    au!
3875    au BufEnter * call setqflist([], 'f')
3876  augroup END
3877  call assert_fails('helpgrep quickfix', 'E925:')
3878  augroup QF_Test
3879    au! BufEnter
3880  augroup END
3881
3882  new | only
3883  augroup QF_Test
3884    au!
3885    au BufEnter * call setqflist([], 'r')
3886  augroup END
3887  call assert_fails('helpgrep quickfix', 'E925:')
3888  augroup QF_Test
3889    au! BufEnter
3890  augroup END
3891
3892  new | only
3893  augroup QF_Test
3894    au!
3895    au BufEnter * call setloclist(0, [], 'r')
3896  augroup END
3897  call assert_fails('lhelpgrep quickfix', 'E926:')
3898  augroup QF_Test
3899    au! BufEnter
3900  augroup END
3901
3902  new | only
3903endfunc
3904
3905" Test for shortening/simplifying the file name when opening the
3906" quickfix window or when displaying the quickfix list
3907func Test_shorten_fname()
3908  if !has('unix')
3909    return
3910  endif
3911  %bwipe
3912  " Create a quickfix list with a absolute path filename
3913  let fname = getcwd() . '/test_quickfix.vim'
3914  call setqflist([], ' ', {'lines':[fname . ":20:Line20"], 'efm':'%f:%l:%m'})
3915  call assert_equal(fname, bufname('test_quickfix.vim'))
3916  " Opening the quickfix window should simplify the file path
3917  cwindow
3918  call assert_equal('test_quickfix.vim', bufname('test_quickfix.vim'))
3919  cclose
3920  %bwipe
3921  " Create a quickfix list with a absolute path filename
3922  call setqflist([], ' ', {'lines':[fname . ":20:Line20"], 'efm':'%f:%l:%m'})
3923  call assert_equal(fname, bufname('test_quickfix.vim'))
3924  " Displaying the quickfix list should simplify the file path
3925  silent! clist
3926  call assert_equal('test_quickfix.vim', bufname('test_quickfix.vim'))
3927endfunc
3928
3929" Quickfix title tests
3930" In the below tests, 'exe "cmd"' is used to invoke the quickfix commands.
3931" Otherwise due to indentation, the title is set with spaces at the beginning
3932" of the command.
3933func Test_qftitle()
3934  call writefile(["F1:1:Line1"], 'Xerr')
3935
3936  " :cexpr
3937  exe "cexpr readfile('Xerr')"
3938  call assert_equal(":cexpr readfile('Xerr')", getqflist({'title' : 1}).title)
3939
3940  " :cgetexpr
3941  exe "cgetexpr readfile('Xerr')"
3942  call assert_equal(":cgetexpr readfile('Xerr')",
3943					\ getqflist({'title' : 1}).title)
3944
3945  " :caddexpr
3946  call setqflist([], 'f')
3947  exe "caddexpr readfile('Xerr')"
3948  call assert_equal(":caddexpr readfile('Xerr')",
3949					\ getqflist({'title' : 1}).title)
3950
3951  " :cbuffer
3952  new Xerr
3953  exe "cbuffer"
3954  call assert_equal(':cbuffer (Xerr)', getqflist({'title' : 1}).title)
3955
3956  " :cgetbuffer
3957  edit Xerr
3958  exe "cgetbuffer"
3959  call assert_equal(':cgetbuffer (Xerr)', getqflist({'title' : 1}).title)
3960
3961  " :caddbuffer
3962  call setqflist([], 'f')
3963  edit Xerr
3964  exe "caddbuffer"
3965  call assert_equal(':caddbuffer (Xerr)', getqflist({'title' : 1}).title)
3966
3967  " :cfile
3968  exe "cfile Xerr"
3969  call assert_equal(':cfile Xerr', getqflist({'title' : 1}).title)
3970
3971  " :cgetfile
3972  exe "cgetfile Xerr"
3973  call assert_equal(':cgetfile Xerr', getqflist({'title' : 1}).title)
3974
3975  " :caddfile
3976  call setqflist([], 'f')
3977  exe "caddfile Xerr"
3978  call assert_equal(':caddfile Xerr', getqflist({'title' : 1}).title)
3979
3980  " :grep
3981  set grepprg=internal
3982  exe "grep F1 Xerr"
3983  call assert_equal(':grep F1 Xerr', getqflist({'title' : 1}).title)
3984
3985  " :grepadd
3986  call setqflist([], 'f')
3987  exe "grepadd F1 Xerr"
3988  call assert_equal(':grepadd F1 Xerr', getqflist({'title' : 1}).title)
3989  set grepprg&vim
3990
3991  " :vimgrep
3992  exe "vimgrep F1 Xerr"
3993  call assert_equal(':vimgrep F1 Xerr', getqflist({'title' : 1}).title)
3994
3995  " :vimgrepadd
3996  call setqflist([], 'f')
3997  exe "vimgrepadd F1 Xerr"
3998  call assert_equal(':vimgrepadd F1 Xerr', getqflist({'title' : 1}).title)
3999
4000  call setqflist(['F1:10:L10'], ' ')
4001  call assert_equal(':setqflist()', getqflist({'title' : 1}).title)
4002
4003  call setqflist([], 'f')
4004  call setqflist(['F1:10:L10'], 'a')
4005  call assert_equal(':setqflist()', getqflist({'title' : 1}).title)
4006
4007  call setqflist([], 'f')
4008  call setqflist(['F1:10:L10'], 'r')
4009  call assert_equal(':setqflist()', getqflist({'title' : 1}).title)
4010
4011  close
4012  call delete('Xerr')
4013
4014  call setqflist([], ' ', {'title' : 'Errors'})
4015  copen
4016  call assert_equal('Errors', w:quickfix_title)
4017  call setqflist([], 'r', {'items' : [{'filename' : 'a.c', 'lnum' : 10}]})
4018  call assert_equal('Errors', w:quickfix_title)
4019  cclose
4020endfunc
4021
4022func Test_lbuffer_with_bwipe()
4023  new
4024  new
4025  augroup nasty
4026    au * * bwipe
4027  augroup END
4028  lbuffer
4029  augroup nasty
4030    au!
4031  augroup END
4032endfunc
4033
4034" Test for an autocmd freeing the quickfix/location list when cexpr/lexpr is
4035" running
4036func Xexpr_acmd_freelist(cchar)
4037  call s:setup_commands(a:cchar)
4038
4039  " This was using freed memory.
4040  augroup nasty
4041    au * * call g:Xsetlist([], 'f')
4042  augroup END
4043  Xexpr "x"
4044  augroup nasty
4045    au!
4046  augroup END
4047endfunc
4048
4049func Test_cexpr_acmd_freelist()
4050  call Xexpr_acmd_freelist('c')
4051  call Xexpr_acmd_freelist('l')
4052endfunc
4053
4054" Test for commands that create a new quickfix/location list and jump to the
4055" first error automatically.
4056func Xjumpto_first_error_test(cchar)
4057  call s:setup_commands(a:cchar)
4058
4059  call s:create_test_file('Xtestfile1')
4060  call s:create_test_file('Xtestfile2')
4061  let l = ['Xtestfile1:2:Line2', 'Xtestfile2:4:Line4']
4062
4063  " Test for cexpr/lexpr
4064  enew
4065  Xexpr l
4066  call assert_equal('Xtestfile1', @%)
4067  call assert_equal(2, line('.'))
4068
4069  " Test for cfile/lfile
4070  enew
4071  call writefile(l, 'Xerr')
4072  Xfile Xerr
4073  call assert_equal('Xtestfile1', @%)
4074  call assert_equal(2, line('.'))
4075
4076  " Test for cbuffer/lbuffer
4077  edit Xerr
4078  Xbuffer
4079  call assert_equal('Xtestfile1', @%)
4080  call assert_equal(2, line('.'))
4081
4082  call delete('Xerr')
4083  call delete('Xtestfile1')
4084  call delete('Xtestfile2')
4085endfunc
4086
4087func Test_jumpto_first_error()
4088  call Xjumpto_first_error_test('c')
4089  call Xjumpto_first_error_test('l')
4090endfunc
4091
4092" Test for a quickfix autocmd changing the quickfix/location list before
4093" jumping to the first error in the new list.
4094func Xautocmd_changelist(cchar)
4095  call s:setup_commands(a:cchar)
4096
4097  " Test for cfile/lfile
4098  call s:create_test_file('Xtestfile1')
4099  call s:create_test_file('Xtestfile2')
4100  Xexpr 'Xtestfile1:2:Line2'
4101  autocmd QuickFixCmdPost * Xolder
4102  call writefile(['Xtestfile2:4:Line4'], 'Xerr')
4103  Xfile Xerr
4104  call assert_equal('Xtestfile2', @%)
4105  call assert_equal(4, line('.'))
4106  autocmd! QuickFixCmdPost
4107
4108  " Test for cbuffer/lbuffer
4109  call g:Xsetlist([], 'f')
4110  Xexpr 'Xtestfile1:2:Line2'
4111  autocmd QuickFixCmdPost * Xolder
4112  call writefile(['Xtestfile2:4:Line4'], 'Xerr')
4113  edit Xerr
4114  Xbuffer
4115  call assert_equal('Xtestfile2', @%)
4116  call assert_equal(4, line('.'))
4117  autocmd! QuickFixCmdPost
4118
4119  " Test for cexpr/lexpr
4120  call g:Xsetlist([], 'f')
4121  Xexpr 'Xtestfile1:2:Line2'
4122  autocmd QuickFixCmdPost * Xolder
4123  Xexpr 'Xtestfile2:4:Line4'
4124  call assert_equal('Xtestfile2', @%)
4125  call assert_equal(4, line('.'))
4126  autocmd! QuickFixCmdPost
4127
4128  " The grepprg may not be set on non-Unix systems
4129  if has('unix')
4130    " Test for grep/lgrep
4131    call g:Xsetlist([], 'f')
4132    Xexpr 'Xtestfile1:2:Line2'
4133    autocmd QuickFixCmdPost * Xolder
4134    silent Xgrep Line5 Xtestfile2
4135    call assert_equal('Xtestfile2', @%)
4136    call assert_equal(5, line('.'))
4137    autocmd! QuickFixCmdPost
4138  endif
4139
4140  " Test for vimgrep/lvimgrep
4141  call g:Xsetlist([], 'f')
4142  Xexpr 'Xtestfile1:2:Line2'
4143  autocmd QuickFixCmdPost * Xolder
4144  silent Xvimgrep Line5 Xtestfile2
4145  call assert_equal('Xtestfile2', @%)
4146  call assert_equal(5, line('.'))
4147  autocmd! QuickFixCmdPost
4148
4149  " Test for autocommands clearing the quickfix list before jumping to the
4150  " first error. This should not result in an error
4151  autocmd QuickFixCmdPost * call g:Xsetlist([], 'r')
4152  let v:errmsg = ''
4153  " Test for cfile/lfile
4154  Xfile Xerr
4155  call assert_true(v:errmsg !~# 'E42:')
4156  " Test for cbuffer/lbuffer
4157  edit Xerr
4158  Xbuffer
4159  call assert_true(v:errmsg !~# 'E42:')
4160  " Test for cexpr/lexpr
4161  Xexpr 'Xtestfile2:4:Line4'
4162  call assert_true(v:errmsg !~# 'E42:')
4163  " Test for grep/lgrep
4164  " The grepprg may not be set on non-Unix systems
4165  if has('unix')
4166    silent Xgrep Line5 Xtestfile2
4167    call assert_true(v:errmsg !~# 'E42:')
4168  endif
4169  " Test for vimgrep/lvimgrep
4170  call assert_fails('silent Xvimgrep Line5 Xtestfile2', 'E480:')
4171  autocmd! QuickFixCmdPost
4172
4173  call delete('Xerr')
4174  call delete('Xtestfile1')
4175  call delete('Xtestfile2')
4176endfunc
4177
4178func Test_autocmd_changelist()
4179  call Xautocmd_changelist('c')
4180  call Xautocmd_changelist('l')
4181endfunc
4182
4183" Tests for the ':filter /pat/ clist' command
4184func Test_filter_clist()
4185  cexpr ['Xfile1:10:10:Line 10', 'Xfile2:15:15:Line 15']
4186  call assert_equal([' 2 Xfile2:15 col 15: Line 15'],
4187			\ split(execute('filter /Line 15/ clist'), "\n"))
4188  call assert_equal([' 1 Xfile1:10 col 10: Line 10'],
4189			\ split(execute('filter /Xfile1/ clist'), "\n"))
4190  call assert_equal([], split(execute('filter /abc/ clist'), "\n"))
4191
4192  call setqflist([{'module' : 'abc', 'pattern' : 'pat1'},
4193			\ {'module' : 'pqr', 'pattern' : 'pat2'}], ' ')
4194  call assert_equal([' 2 pqr:pat2:  '],
4195			\ split(execute('filter /pqr/ clist'), "\n"))
4196  call assert_equal([' 1 abc:pat1:  '],
4197			\ split(execute('filter /pat1/ clist'), "\n"))
4198endfunc
4199
4200" Tests for the "CTRL-W <CR>" command.
4201func Xview_result_split_tests(cchar)
4202  call s:setup_commands(a:cchar)
4203
4204  " Test that "CTRL-W <CR>" in a qf/ll window fails with empty list.
4205  call g:Xsetlist([])
4206  Xopen
4207  let l:win_count = winnr('$')
4208  call assert_fails('execute "normal! \<C-W>\<CR>"', 'E42')
4209  call assert_equal(l:win_count, winnr('$'))
4210  Xclose
4211endfunc
4212
4213func Test_view_result_split()
4214  call Xview_result_split_tests('c')
4215  call Xview_result_split_tests('l')
4216endfunc
4217
4218" Test that :cc sets curswant
4219func Test_curswant()
4220  helpgrep quickfix
4221  normal! llll
4222  1cc
4223  call assert_equal(getcurpos()[4], virtcol('.'))
4224  cclose | helpclose
4225endfunc
4226
4227" Test for opening a file from the quickfix window using CTRL-W <Enter>
4228" doesn't leave an empty buffer around.
4229func Test_splitview()
4230  call s:create_test_file('Xtestfile1')
4231  call s:create_test_file('Xtestfile2')
4232  new | only
4233  let last_bufnr = bufnr('Test_sv_1', 1)
4234  let l = ['Xtestfile1:2:Line2', 'Xtestfile2:4:Line4']
4235  cgetexpr l
4236  copen
4237  let numbufs = len(getbufinfo())
4238  exe "normal \<C-W>\<CR>"
4239  copen
4240  exe "normal j\<C-W>\<CR>"
4241  " Make sure new empty buffers are not created
4242  call assert_equal(numbufs, len(getbufinfo()))
4243  " Creating a new buffer should use the next available buffer number
4244  call assert_equal(last_bufnr + 4, bufnr("Test_sv_2", 1))
4245  bwipe Test_sv_1
4246  bwipe Test_sv_2
4247  new | only
4248
4249  " When split opening files from location list window, make sure that two
4250  " windows doesn't refer to the same location list
4251  lgetexpr l
4252  let locid = getloclist(0, {'id' : 0}).id
4253  lopen
4254  exe "normal \<C-W>\<CR>"
4255  call assert_notequal(locid, getloclist(0, {'id' : 0}).id)
4256  call assert_equal(0, getloclist(0, {'winid' : 0}).winid)
4257  new | only
4258
4259  " When split opening files from a helpgrep location list window, a new help
4260  " window should be opened with a copy of the location list.
4261  lhelpgrep window
4262  let locid = getloclist(0, {'id' : 0}).id
4263  lwindow
4264  exe "normal j\<C-W>\<CR>"
4265  call assert_notequal(locid, getloclist(0, {'id' : 0}).id)
4266  call assert_equal(0, getloclist(0, {'winid' : 0}).winid)
4267  new | only
4268
4269  " Using :split or :vsplit from a quickfix window should behave like a :new
4270  " or a :vnew command
4271  copen
4272  split
4273  call assert_equal(3, winnr('$'))
4274  let l = getwininfo()
4275  call assert_equal([0, 0, 1], [l[0].quickfix, l[1].quickfix, l[2].quickfix])
4276  close
4277  copen
4278  vsplit
4279  let l = getwininfo()
4280  call assert_equal([0, 0, 1], [l[0].quickfix, l[1].quickfix, l[2].quickfix])
4281  new | only
4282
4283  call delete('Xtestfile1')
4284  call delete('Xtestfile2')
4285endfunc
4286
4287" Test for parsing entries using visual screen column
4288func Test_viscol()
4289  enew
4290  call writefile(["Col1\tCol2\tCol3"], 'Xfile1')
4291  edit Xfile1
4292
4293  " Use byte offset for column number
4294  set efm&
4295  cexpr "Xfile1:1:5:XX\nXfile1:1:9:YY\nXfile1:1:20:ZZ"
4296  call assert_equal([5, 8], [col('.'), virtcol('.')])
4297  cnext
4298  call assert_equal([9, 12], [col('.'), virtcol('.')])
4299  cnext
4300  call assert_equal([14, 20], [col('.'), virtcol('.')])
4301
4302  " Use screen column offset for column number
4303  set efm=%f:%l:%v:%m
4304  cexpr "Xfile1:1:8:XX\nXfile1:1:12:YY\nXfile1:1:20:ZZ"
4305  call assert_equal([5, 8], [col('.'), virtcol('.')])
4306  cnext
4307  call assert_equal([9, 12], [col('.'), virtcol('.')])
4308  cnext
4309  call assert_equal([14, 20], [col('.'), virtcol('.')])
4310  cexpr "Xfile1:1:6:XX\nXfile1:1:15:YY\nXfile1:1:24:ZZ"
4311  call assert_equal([5, 8], [col('.'), virtcol('.')])
4312  cnext
4313  call assert_equal([10, 16], [col('.'), virtcol('.')])
4314  cnext
4315  call assert_equal([14, 20], [col('.'), virtcol('.')])
4316
4317  enew
4318  call writefile(["Col1\täü\töß\tCol4"], 'Xfile1')
4319
4320  " Use byte offset for column number
4321  set efm&
4322  cexpr "Xfile1:1:8:XX\nXfile1:1:11:YY\nXfile1:1:16:ZZ"
4323  call assert_equal([8, 10], [col('.'), virtcol('.')])
4324  cnext
4325  call assert_equal([11, 17], [col('.'), virtcol('.')])
4326  cnext
4327  call assert_equal([16, 25], [col('.'), virtcol('.')])
4328
4329  " Use screen column offset for column number
4330  set efm=%f:%l:%v:%m
4331  cexpr "Xfile1:1:10:XX\nXfile1:1:17:YY\nXfile1:1:25:ZZ"
4332  call assert_equal([8, 10], [col('.'), virtcol('.')])
4333  cnext
4334  call assert_equal([11, 17], [col('.'), virtcol('.')])
4335  cnext
4336  call assert_equal([16, 25], [col('.'), virtcol('.')])
4337
4338  enew | only
4339  set efm&
4340  call delete('Xfile1')
4341endfunc
4342
4343" Test for the quickfix window buffer
4344func Xqfbuf_test(cchar)
4345  call s:setup_commands(a:cchar)
4346
4347  " Quickfix buffer should be reused across closing and opening a quickfix
4348  " window
4349  Xexpr "F1:10:Line10"
4350  Xopen
4351  let qfbnum = bufnr('')
4352  Xclose
4353  " Even after the quickfix window is closed, the buffer should be loaded
4354  call assert_true(bufloaded(qfbnum))
4355  call assert_true(qfbnum, g:Xgetlist({'qfbufnr' : 0}).qfbufnr)
4356  Xopen
4357  " Buffer should be reused when opening the window again
4358  call assert_equal(qfbnum, bufnr(''))
4359  Xclose
4360
4361  if a:cchar == 'l'
4362    %bwipe
4363    " For a location list, when both the file window and the location list
4364    " window for the list are closed, then the buffer should be freed.
4365    new | only
4366    lexpr "F1:10:Line10"
4367    let wid = win_getid()
4368    lopen
4369    let qfbnum = bufnr('')
4370    call assert_match(qfbnum . ' %a-  "\[Location List]"', execute('ls'))
4371    close
4372    " When the location list window is closed, the buffer name should not
4373    " change to 'Quickfix List'
4374    call assert_match(qfbnum . 'u h-  "\[Location List]"', execute('ls!'))
4375    call assert_true(bufloaded(qfbnum))
4376
4377    " After deleting a location list buffer using ":bdelete", opening the
4378    " location list window should mark the buffer as a location list buffer.
4379    exe "bdelete " . qfbnum
4380    lopen
4381    call assert_equal("quickfix", &buftype)
4382    call assert_equal(1, getwininfo(win_getid(winnr()))[0].loclist)
4383    call assert_equal(wid, getloclist(0, {'filewinid' : 0}).filewinid)
4384    call assert_false(&swapfile)
4385    lclose
4386
4387    " When the location list is cleared for the window, the buffer should be
4388    " removed
4389    call setloclist(0, [], 'f')
4390    call assert_false(bufexists(qfbnum))
4391    call assert_equal(0, getloclist(0, {'qfbufnr' : 0}).qfbufnr)
4392
4393    " When the location list is freed with the location list window open, the
4394    " location list buffer should not be lost. It should be reused when the
4395    " location list is again populated.
4396    lexpr "F1:10:Line10"
4397    lopen
4398    let wid = win_getid()
4399    let qfbnum = bufnr('')
4400    wincmd p
4401    call setloclist(0, [], 'f')
4402    lexpr "F1:10:Line10"
4403    lopen
4404    call assert_equal(wid, win_getid())
4405    call assert_equal(qfbnum, bufnr(''))
4406    lclose
4407
4408    " When the window with the location list is closed, the buffer should be
4409    " removed
4410    new | only
4411    call assert_false(bufexists(qfbnum))
4412  endif
4413endfunc
4414
4415func Test_qfbuf()
4416  call Xqfbuf_test('c')
4417  call Xqfbuf_test('l')
4418endfunc
4419
4420" If there is an autocmd to use only one window, then opening the location
4421" list window used to crash Vim.
4422func Test_winonly_autocmd()
4423  call s:create_test_file('Xtest1')
4424  " Autocmd to show only one Vim window at a time
4425  autocmd WinEnter * only
4426  new
4427  " Load the location list
4428  lexpr "Xtest1:5:Line5\nXtest1:10:Line10\nXtest1:15:Line15"
4429  let loclistid = getloclist(0, {'id' : 0}).id
4430  " Open the location list window. Only this window will be shown and the file
4431  " window is closed.
4432  lopen
4433  call assert_equal(loclistid, getloclist(0, {'id' : 0}).id)
4434  " Jump to an entry in the location list and make sure that the cursor is
4435  " positioned correctly.
4436  ll 3
4437  call assert_equal(loclistid, getloclist(0, {'id' : 0}).id)
4438  call assert_equal('Xtest1', @%)
4439  call assert_equal(15, line('.'))
4440  " Cleanup
4441  autocmd! WinEnter
4442  new | only
4443  call delete('Xtest1')
4444endfunc
4445
4446" Test to make sure that an empty quickfix buffer is not reused for loading
4447" a normal buffer.
4448func Test_empty_qfbuf()
4449  enew | only
4450  call writefile(["Test"], 'Xfile1')
4451  call setqflist([], 'f')
4452  copen | only
4453  let qfbuf = bufnr('')
4454  edit Xfile1
4455  call assert_notequal(qfbuf, bufnr(''))
4456  enew
4457  call delete('Xfile1')
4458endfunc
4459
4460" Test for the :cbelow, :cabove, :lbelow and :labove commands.
4461" And for the :cafter, :cbefore, :lafter and :lbefore commands.
4462func Xtest_below(cchar)
4463  call s:setup_commands(a:cchar)
4464
4465  " No quickfix/location list
4466  call assert_fails('Xbelow', 'E42:')
4467  call assert_fails('Xabove', 'E42:')
4468  call assert_fails('Xbefore', 'E42:')
4469  call assert_fails('Xafter', 'E42:')
4470
4471  " Empty quickfix/location list
4472  call g:Xsetlist([])
4473  call assert_fails('Xbelow', 'E42:')
4474  call assert_fails('Xabove', 'E42:')
4475  call assert_fails('Xbefore', 'E42:')
4476  call assert_fails('Xafter', 'E42:')
4477
4478  call s:create_test_file('X1')
4479  call s:create_test_file('X2')
4480  call s:create_test_file('X3')
4481  call s:create_test_file('X4')
4482
4483  " Invalid entries
4484  edit X1
4485  call g:Xsetlist(["E1", "E2"])
4486  call assert_fails('Xbelow', 'E42:')
4487  call assert_fails('Xabove', 'E42:')
4488  call assert_fails('3Xbelow', 'E42:')
4489  call assert_fails('4Xabove', 'E42:')
4490  call assert_fails('Xbefore', 'E42:')
4491  call assert_fails('Xafter', 'E42:')
4492  call assert_fails('3Xbefore', 'E42:')
4493  call assert_fails('4Xafter', 'E42:')
4494
4495  " Test the commands with various arguments
4496  Xexpr ["X1:5:3:L5", "X2:5:2:L5", "X2:10:3:L10", "X2:15:4:L15", "X3:3:5:L3"]
4497  edit +7 X2
4498  Xabove
4499  call assert_equal(['X2', 5], [@%, line('.')])
4500  call assert_fails('Xabove', 'E553:')
4501  normal 7G
4502  Xbefore
4503  call assert_equal(['X2', 5, 2], [@%, line('.'), col('.')])
4504  call assert_fails('Xbefore', 'E553:')
4505
4506  normal 2j
4507  Xbelow
4508  call assert_equal(['X2', 10], [@%, line('.')])
4509  normal 7G
4510  Xafter
4511  call assert_equal(['X2', 10, 3], [@%, line('.'), col('.')])
4512
4513  " Last error in this file
4514  Xbelow 99
4515  call assert_equal(['X2', 15], [@%, line('.')])
4516  call assert_fails('Xbelow', 'E553:')
4517  normal gg
4518  Xafter 99
4519  call assert_equal(['X2', 15, 4], [@%, line('.'), col('.')])
4520  call assert_fails('Xafter', 'E553:')
4521
4522  " First error in this file
4523  Xabove 99
4524  call assert_equal(['X2', 5], [@%, line('.')])
4525  call assert_fails('Xabove', 'E553:')
4526  normal G
4527  Xbefore 99
4528  call assert_equal(['X2', 5, 2], [@%, line('.'), col('.')])
4529  call assert_fails('Xbefore', 'E553:')
4530
4531  normal gg
4532  Xbelow 2
4533  call assert_equal(['X2', 10], [@%, line('.')])
4534  normal gg
4535  Xafter 2
4536  call assert_equal(['X2', 10, 3], [@%, line('.'), col('.')])
4537
4538  normal G
4539  Xabove 2
4540  call assert_equal(['X2', 10], [@%, line('.')])
4541  normal G
4542  Xbefore 2
4543  call assert_equal(['X2', 10, 3], [@%, line('.'), col('.')])
4544
4545  edit X4
4546  call assert_fails('Xabove', 'E42:')
4547  call assert_fails('Xbelow', 'E42:')
4548  call assert_fails('Xbefore', 'E42:')
4549  call assert_fails('Xafter', 'E42:')
4550  if a:cchar == 'l'
4551    " If a buffer has location list entries from some other window but not
4552    " from the current window, then the commands should fail.
4553    edit X1 | split | call setloclist(0, [], 'f')
4554    call assert_fails('Xabove', 'E776:')
4555    call assert_fails('Xbelow', 'E776:')
4556    call assert_fails('Xbefore', 'E776:')
4557    call assert_fails('Xafter', 'E776:')
4558    close
4559  endif
4560
4561  " Test for lines with multiple quickfix entries
4562  Xexpr ["X1:5:L5", "X2:5:1:L5_1", "X2:5:2:L5_2", "X2:5:3:L5_3",
4563	      \ "X2:10:1:L10_1", "X2:10:2:L10_2", "X2:10:3:L10_3",
4564	      \ "X2:15:1:L15_1", "X2:15:2:L15_2", "X2:15:3:L15_3", "X3:3:L3"]
4565  edit +1 X2
4566  Xbelow 2
4567  call assert_equal(['X2', 10, 1], [@%, line('.'), col('.')])
4568  normal 1G
4569  Xafter 2
4570  call assert_equal(['X2', 5, 2], [@%, line('.'), col('.')])
4571
4572  normal gg
4573  Xbelow 99
4574  call assert_equal(['X2', 15, 1], [@%, line('.'), col('.')])
4575  normal gg
4576  Xafter 99
4577  call assert_equal(['X2', 15, 3], [@%, line('.'), col('.')])
4578
4579  normal G
4580  Xabove 2
4581  call assert_equal(['X2', 10, 1], [@%, line('.'), col('.')])
4582  normal G
4583  Xbefore 2
4584  call assert_equal(['X2', 15, 2], [@%, line('.'), col('.')])
4585
4586  normal G
4587  Xabove 99
4588  call assert_equal(['X2', 5, 1], [@%, line('.'), col('.')])
4589  normal G
4590  Xbefore 99
4591  call assert_equal(['X2', 5, 1], [@%, line('.'), col('.')])
4592
4593  normal 10G
4594  Xabove
4595  call assert_equal(['X2', 5, 1], [@%, line('.'), col('.')])
4596  normal 10G$
4597  2Xbefore
4598  call assert_equal(['X2', 10, 2], [@%, line('.'), col('.')])
4599
4600  normal 10G
4601  Xbelow
4602  call assert_equal(['X2', 15, 1], [@%, line('.'), col('.')])
4603  normal 9G
4604  5Xafter
4605  call assert_equal(['X2', 15, 2], [@%, line('.'), col('.')])
4606
4607  " Invalid range
4608  if a:cchar == 'c'
4609    call assert_fails('-2cbelow', 'E16:')
4610    call assert_fails('-2cafter', 'E16:')
4611  else
4612    call assert_fails('-2lbelow', 'E16:')
4613    call assert_fails('-2lafter', 'E16:')
4614  endif
4615
4616  call delete('X1')
4617  call delete('X2')
4618  call delete('X3')
4619  call delete('X4')
4620endfunc
4621
4622func Test_cbelow()
4623  call Xtest_below('c')
4624  call Xtest_below('l')
4625endfunc
4626
4627func Test_quickfix_count()
4628  let commands = [
4629	\ 'cNext',
4630	\ 'cNfile',
4631	\ 'cabove',
4632	\ 'cbelow',
4633	\ 'cfirst',
4634	\ 'clast',
4635	\ 'cnewer',
4636	\ 'cnext',
4637	\ 'cnfile',
4638	\ 'colder',
4639	\ 'cprevious',
4640	\ 'crewind',
4641	\
4642	\ 'lNext',
4643	\ 'lNfile',
4644	\ 'labove',
4645	\ 'lbelow',
4646	\ 'lfirst',
4647	\ 'llast',
4648	\ 'lnewer',
4649	\ 'lnext',
4650	\ 'lnfile',
4651	\ 'lolder',
4652	\ 'lprevious',
4653	\ 'lrewind',
4654	\ ]
4655  for cmd in commands
4656    call assert_fails('-1' .. cmd, 'E16:')
4657    call assert_fails('.' .. cmd, 'E16:')
4658    call assert_fails('%' .. cmd, 'E16:')
4659    call assert_fails('$' .. cmd, 'E16:')
4660  endfor
4661endfunc
4662
4663" Test for aborting quickfix commands using QuickFixCmdPre
4664func Xtest_qfcmd_abort(cchar)
4665  call s:setup_commands(a:cchar)
4666
4667  call g:Xsetlist([], 'f')
4668
4669  " cexpr/lexpr
4670  let e = ''
4671  try
4672    Xexpr ["F1:10:Line10", "F2:20:Line20"]
4673  catch /.*/
4674    let e = v:exception
4675  endtry
4676  call assert_equal('AbortCmd', e)
4677  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4678
4679  " cfile/lfile
4680  call writefile(["F1:10:Line10", "F2:20:Line20"], 'Xfile1')
4681  let e = ''
4682  try
4683    Xfile Xfile1
4684  catch /.*/
4685    let e = v:exception
4686  endtry
4687  call assert_equal('AbortCmd', e)
4688  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4689  call delete('Xfile1')
4690
4691  " cgetbuffer/lgetbuffer
4692  enew!
4693  call append(0, ["F1:10:Line10", "F2:20:Line20"])
4694  let e = ''
4695  try
4696    Xgetbuffer
4697  catch /.*/
4698    let e = v:exception
4699  endtry
4700  call assert_equal('AbortCmd', e)
4701  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4702  enew!
4703
4704  " vimgrep/lvimgrep
4705  let e = ''
4706  try
4707    Xvimgrep /func/ test_quickfix.vim
4708  catch /.*/
4709    let e = v:exception
4710  endtry
4711  call assert_equal('AbortCmd', e)
4712  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4713
4714  " helpgrep/lhelpgrep
4715  let e = ''
4716  try
4717    Xhelpgrep quickfix
4718  catch /.*/
4719    let e = v:exception
4720  endtry
4721  call assert_equal('AbortCmd', e)
4722  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4723
4724  " grep/lgrep
4725  if has('unix')
4726    let e = ''
4727    try
4728      silent Xgrep func test_quickfix.vim
4729    catch /.*/
4730      let e = v:exception
4731    endtry
4732    call assert_equal('AbortCmd', e)
4733    call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4734  endif
4735endfunc
4736
4737func Test_qfcmd_abort()
4738  augroup QF_Test
4739    au!
4740    autocmd  QuickFixCmdPre * throw "AbortCmd"
4741  augroup END
4742
4743  call Xtest_qfcmd_abort('c')
4744  call Xtest_qfcmd_abort('l')
4745
4746  augroup QF_Test
4747    au!
4748  augroup END
4749endfunc
4750
4751" Test for using a file in one of the parent directories.
4752func Test_search_in_dirstack()
4753  call mkdir('Xtestdir/a/b/c', 'p')
4754  let save_cwd = getcwd()
4755  call writefile(["X1_L1", "X1_L2"], 'Xtestdir/Xfile1')
4756  call writefile(["X2_L1", "X2_L2"], 'Xtestdir/a/Xfile2')
4757  call writefile(["X3_L1", "X3_L2"], 'Xtestdir/a/b/Xfile3')
4758  call writefile(["X4_L1", "X4_L2"], 'Xtestdir/a/b/c/Xfile4')
4759
4760  let lines = "Entering dir Xtestdir\n" .
4761	      \ "Entering dir a\n" .
4762	      \ "Entering dir b\n" .
4763	      \ "Xfile2:2:X2_L2\n" .
4764	      \ "Leaving dir a\n" .
4765	      \ "Xfile1:2:X1_L2\n" .
4766	      \ "Xfile3:1:X3_L1\n" .
4767	      \ "Entering dir c\n" .
4768	      \ "Xfile4:2:X4_L2\n" .
4769	      \ "Leaving dir c\n"
4770  set efm=%DEntering\ dir\ %f,%XLeaving\ dir\ %f,%f:%l:%m
4771  cexpr lines .. "Leaving dir Xtestdir|\n" | let next = 1
4772  call assert_equal(11, getqflist({'size' : 0}).size)
4773  call assert_equal(4, getqflist({'idx' : 0}).idx)
4774  call assert_equal('X2_L2', getline('.'))
4775  call assert_equal(1, next)
4776  cnext
4777  call assert_equal(6, getqflist({'idx' : 0}).idx)
4778  call assert_equal('X1_L2', getline('.'))
4779  cnext
4780  call assert_equal(7, getqflist({'idx' : 0}).idx)
4781  call assert_equal(1, line('$'))
4782  call assert_equal('', getline(1))
4783  cnext
4784  call assert_equal(9, getqflist({'idx' : 0}).idx)
4785  call assert_equal(1, line('$'))
4786  call assert_equal('', getline(1))
4787
4788  set efm&
4789  exe 'cd ' . save_cwd
4790  call delete('Xtestdir', 'rf')
4791endfunc
4792
4793" Test for :cquit
4794func Test_cquit()
4795  " Exit Vim with a non-zero value
4796  if RunVim([], ["cquit 7"], '')
4797    call assert_equal(7, v:shell_error)
4798  endif
4799
4800  if RunVim([], ["50cquit"], '')
4801    call assert_equal(50, v:shell_error)
4802  endif
4803
4804  " Exit Vim with default value
4805  if RunVim([], ["cquit"], '')
4806    call assert_equal(1, v:shell_error)
4807  endif
4808
4809  " Exit Vim with zero value
4810  if RunVim([], ["cquit 0"], '')
4811    call assert_equal(0, v:shell_error)
4812  endif
4813
4814  " Exit Vim with negative value
4815  call assert_fails('-3cquit', 'E16:')
4816endfunc
4817
4818" Test for getting a specific item from a quickfix list
4819func Xtest_getqflist_by_idx(cchar)
4820  call s:setup_commands(a:cchar)
4821  " Empty list
4822  call assert_equal([], g:Xgetlist({'idx' : 1, 'items' : 0}).items)
4823  Xexpr ['F1:10:L10', 'F1:20:L20']
4824  let l = g:Xgetlist({'idx' : 2, 'items' : 0}).items
4825  call assert_equal(bufnr('F1'), l[0].bufnr)
4826  call assert_equal(20, l[0].lnum)
4827  call assert_equal('L20', l[0].text)
4828  call assert_equal([], g:Xgetlist({'idx' : -1, 'items' : 0}).items)
4829  call assert_equal([], g:Xgetlist({'idx' : 3, 'items' : 0}).items)
4830  %bwipe!
4831endfunc
4832
4833func Test_getqflist_by_idx()
4834  call Xtest_getqflist_by_idx('c')
4835  call Xtest_getqflist_by_idx('l')
4836endfunc
4837
4838" Test for the 'quickfixtextfunc' setting
4839func Tqfexpr(info)
4840  if a:info.quickfix
4841    let qfl = getqflist({'id' : a:info.id, 'items' : 1}).items
4842  else
4843    let qfl = getloclist(a:info.winid, {'id' : a:info.id, 'items' : 1}).items
4844  endif
4845
4846  let l = []
4847  for idx in range(a:info.start_idx - 1, a:info.end_idx - 1)
4848    let e = qfl[idx]
4849    let s = ''
4850    if e.bufnr != 0
4851      let bname = bufname(e.bufnr)
4852      let s ..= fnamemodify(bname, ':.')
4853    endif
4854    let s ..= '-'
4855    let s ..= 'L' .. string(e.lnum) .. 'C' .. string(e.col) .. '-'
4856    let s ..= e.text
4857    call add(l, s)
4858  endfor
4859
4860  return l
4861endfunc
4862
4863func Xtest_qftextfunc(cchar)
4864  call s:setup_commands(a:cchar)
4865
4866  set efm=%f:%l:%c:%m
4867  set quickfixtextfunc=Tqfexpr
4868  Xexpr ['F1:10:2:green', 'F1:20:4:blue']
4869  Xwindow
4870  call assert_equal('F1-L10C2-green', getline(1))
4871  call assert_equal('F1-L20C4-blue', getline(2))
4872  Xclose
4873  set quickfixtextfunc&vim
4874  Xwindow
4875  call assert_equal('F1|10 col 2| green', getline(1))
4876  call assert_equal('F1|20 col 4| blue', getline(2))
4877  Xclose
4878  set efm&
4879  set quickfixtextfunc&
4880
4881  " Test for per list 'quickfixtextfunc' setting
4882  func PerQfText(info)
4883    if a:info.quickfix
4884      let qfl = getqflist({'id' : a:info.id, 'items' : 1}).items
4885    else
4886      let qfl = getloclist(a:info.winid, {'id' : a:info.id, 'items' : 1}).items
4887    endif
4888    if empty(qfl)
4889      return []
4890    endif
4891    let l = []
4892    for idx in range(a:info.start_idx - 1, a:info.end_idx - 1)
4893      call add(l, 'Line ' .. qfl[idx].lnum .. ', Col ' .. qfl[idx].col)
4894    endfor
4895    return l
4896  endfunc
4897  set quickfixtextfunc=Tqfexpr
4898  call g:Xsetlist([], ' ', {'quickfixtextfunc' : "PerQfText"})
4899  Xaddexpr ['F1:10:2:green', 'F1:20:4:blue']
4900  Xwindow
4901  call assert_equal('Line 10, Col 2', getline(1))
4902  call assert_equal('Line 20, Col 4', getline(2))
4903  Xclose
4904  " Add entries to the list when the quickfix buffer is hidden
4905  Xaddexpr ['F1:30:6:red']
4906  Xwindow
4907  call assert_equal('Line 30, Col 6', getline(3))
4908  Xclose
4909  call g:Xsetlist([], 'r', {'quickfixtextfunc' : ''})
4910  set quickfixtextfunc&
4911  delfunc PerQfText
4912
4913  " Non-existing function
4914  set quickfixtextfunc=Tabc
4915  call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue']", 'E117:')
4916  call assert_fails("Xwindow", 'E117:')
4917  Xclose
4918  set quickfixtextfunc&
4919
4920  " set option to a non-function
4921  set quickfixtextfunc=[10,\ 20]
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 function with different set of arguments
4928  func Xqftext(a, b, c)
4929    return a:a .. a:b .. a:c
4930  endfunc
4931  set quickfixtextfunc=Xqftext
4932  call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue']", 'E119:')
4933  call assert_fails("Xwindow", 'E119:')
4934  Xclose
4935
4936  " set option to a function that returns a list with non-strings
4937  func Xqftext2(d)
4938    return ['one', [], 'two']
4939  endfunc
4940  set quickfixtextfunc=Xqftext2
4941  call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue', 'F1:30:6:red']",
4942                                                                  \ 'E730:')
4943  call assert_fails('Xwindow', 'E730:')
4944  call assert_equal(['one', 'F1|20 col 4| blue', 'two'], getline(1, '$'))
4945  Xclose
4946
4947  set quickfixtextfunc&
4948  delfunc Xqftext
4949  delfunc Xqftext2
4950endfunc
4951
4952func Test_qftextfunc()
4953  call Xtest_qftextfunc('c')
4954  call Xtest_qftextfunc('l')
4955endfunc
4956
4957" Running :lhelpgrep command more than once in a help window, doesn't jump to
4958" the help topic
4959func Test_lhelpgrep_from_help_window()
4960  call mkdir('Xtestdir/doc', 'p')
4961  call writefile(['window'], 'Xtestdir/doc/a.txt')
4962  call writefile(['buffer'], 'Xtestdir/doc/b.txt')
4963  let save_rtp = &rtp
4964  let &rtp = 'Xtestdir'
4965  lhelpgrep window
4966  lhelpgrep buffer
4967  call assert_equal('b.txt', fnamemodify(@%, ":p:t"))
4968  lhelpgrep window
4969  call assert_equal('a.txt', fnamemodify(@%, ":p:t"))
4970  let &rtp = save_rtp
4971  call delete('Xtestdir', 'rf')
4972  new | only!
4973endfunc
4974
4975" vim: shiftwidth=2 sts=2 expandtab
4976