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