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	set t_u7=
2714	call setline(1, ['some', 'text', 'with', 'matches'])
2715	write XCwindow
2716	vimgrep e XCwindow
2717	redraw
2718	cwindow 4
2719  END
2720  call writefile(lines, 'XtestCwindow')
2721  let buf = RunVimInTerminal('-S XtestCwindow', #{rows: 12})
2722  call VerifyScreenDump(buf, 'Test_quickfix_cwindow_1', {})
2723
2724  call term_sendkeys(buf, ":cnext\<CR>")
2725  call VerifyScreenDump(buf, 'Test_quickfix_cwindow_2', {})
2726
2727  " clean up
2728  call StopVimInTerminal(buf)
2729  call delete('XtestCwindow')
2730  call delete('XCwindow')
2731endfunc
2732
2733func XvimgrepTests(cchar)
2734  call s:setup_commands(a:cchar)
2735
2736  call writefile(['Editor:VIM vim',
2737	      \ 'Editor:Emacs EmAcS',
2738	      \ 'Editor:Notepad NOTEPAD'], 'Xtestfile1')
2739  call writefile(['Linux', 'MacOS', 'MS-Windows'], 'Xtestfile2')
2740
2741  " Error cases
2742  call assert_fails('Xvimgrep /abc *', 'E682:')
2743
2744  let @/=''
2745  call assert_fails('Xvimgrep // *', 'E35:')
2746
2747  call assert_fails('Xvimgrep abc', 'E683:')
2748  call assert_fails('Xvimgrep a1b2c3 Xtestfile1', 'E480:')
2749  call assert_fails('Xvimgrep pat Xa1b2c3', 'E480:')
2750
2751  Xexpr ""
2752  Xvimgrepadd Notepad Xtestfile1
2753  Xvimgrepadd MacOS Xtestfile2
2754  let l = g:Xgetlist()
2755  call assert_equal(2, len(l))
2756  call assert_equal('Editor:Notepad NOTEPAD', l[0].text)
2757
2758  10Xvimgrep #\cvim#g Xtestfile?
2759  let l = g:Xgetlist()
2760  call assert_equal(2, len(l))
2761  call assert_equal(8, l[0].col)
2762  call assert_equal(12, l[1].col)
2763
2764  1Xvimgrep ?Editor? Xtestfile*
2765  let l = g:Xgetlist()
2766  call assert_equal(1, len(l))
2767  call assert_equal('Editor:VIM vim', l[0].text)
2768
2769  edit +3 Xtestfile2
2770  Xvimgrep +\cemacs+j Xtestfile1
2771  let l = g:Xgetlist()
2772  call assert_equal('Xtestfile2', bufname(''))
2773  call assert_equal('Editor:Emacs EmAcS', l[0].text)
2774
2775  " Test for unloading a buffer after vimgrep searched the buffer
2776  %bwipe
2777  Xvimgrep /Editor/j Xtestfile*
2778  call assert_equal(0, getbufinfo('Xtestfile1')[0].loaded)
2779  call assert_equal([], getbufinfo('Xtestfile2'))
2780
2781  call delete('Xtestfile1')
2782  call delete('Xtestfile2')
2783endfunc
2784
2785" Tests for the :vimgrep command
2786func Test_vimgrep()
2787  call XvimgrepTests('c')
2788  call XvimgrepTests('l')
2789endfunc
2790
2791" Test for incsearch highlighting of the :vimgrep pattern
2792" This test used to cause "E315: ml_get: invalid lnum" errors.
2793func Test_vimgrep_incsearch()
2794  enew
2795  set incsearch
2796  call test_override("char_avail", 1)
2797
2798  call feedkeys(":2vimgrep assert test_quickfix.vim test_cdo.vim\<CR>", "ntx")
2799  let l = getqflist()
2800  call assert_equal(2, len(l))
2801
2802  call test_override("ALL", 0)
2803  set noincsearch
2804endfunc
2805
2806" Test vimgrep with the last search pattern not set
2807func Test_vimgrep_with_no_last_search_pat()
2808  let lines =<< trim [SCRIPT]
2809    call assert_fails('vimgrep // *', 'E35:')
2810    call writefile(v:errors, 'Xresult')
2811    qall!
2812  [SCRIPT]
2813  call writefile(lines, 'Xscript')
2814  if RunVim([], [], '--clean -S Xscript')
2815    call assert_equal([], readfile('Xresult'))
2816  endif
2817  call delete('Xscript')
2818  call delete('Xresult')
2819endfunc
2820
2821func XfreeTests(cchar)
2822  call s:setup_commands(a:cchar)
2823
2824  enew | only
2825
2826  " Deleting the quickfix stack should work even When the current list is
2827  " somewhere in the middle of the stack
2828  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2829  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2830  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2831  Xolder
2832  call g:Xsetlist([], 'f')
2833  call assert_equal(0, len(g:Xgetlist()))
2834
2835  " After deleting the stack, adding a new list should create a stack with a
2836  " single list.
2837  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2838  call assert_equal(1, g:Xgetlist({'all':1}).nr)
2839
2840  " Deleting the stack from a quickfix window should update/clear the
2841  " quickfix/location list window.
2842  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2843  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2844  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2845  Xolder
2846  Xwindow
2847  call g:Xsetlist([], 'f')
2848  call assert_equal(2, winnr('$'))
2849  call assert_equal(1, line('$'))
2850  Xclose
2851
2852  " Deleting the stack from a non-quickfix window should update/clear the
2853  " quickfix/location list window.
2854  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2855  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2856  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2857  Xolder
2858  Xwindow
2859  wincmd p
2860  call g:Xsetlist([], 'f')
2861  call assert_equal(0, len(g:Xgetlist()))
2862  wincmd p
2863  call assert_equal(2, winnr('$'))
2864  call assert_equal(1, line('$'))
2865
2866  " After deleting the location list stack, if the location list window is
2867  " opened, then a new location list should be created. So opening the
2868  " location list window again should not create a new window.
2869  if a:cchar == 'l'
2870      lexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2871      wincmd p
2872      lopen
2873      call assert_equal(2, winnr('$'))
2874  endif
2875  Xclose
2876endfunc
2877
2878" Tests for the quickfix free functionality
2879func Test_qf_free()
2880  call XfreeTests('c')
2881  call XfreeTests('l')
2882endfunc
2883
2884" Test for buffer overflow when parsing lines and adding new entries to
2885" the quickfix list.
2886func Test_bufoverflow()
2887  set efm=%f:%l:%m
2888  cgetexpr ['File1:100:' . repeat('x', 1025)]
2889
2890  set efm=%+GCompiler:\ %.%#,%f:%l:%m
2891  cgetexpr ['Compiler: ' . repeat('a', 1015), 'File1:10:Hello World']
2892
2893  set efm=%DEntering\ directory\ %f,%f:%l:%m
2894  cgetexpr ['Entering directory ' . repeat('a', 1006),
2895	      \ 'File1:10:Hello World']
2896  set efm&vim
2897endfunc
2898
2899" Tests for getting the quickfix stack size
2900func XsizeTests(cchar)
2901  call s:setup_commands(a:cchar)
2902
2903  call g:Xsetlist([], 'f')
2904  call assert_equal(0, g:Xgetlist({'nr':'$'}).nr)
2905  call assert_equal('', g:Xgetlist({'nr':'$', 'all':1}).title)
2906  call assert_equal(0, g:Xgetlist({'nr':0}).nr)
2907
2908  Xexpr "File1:10:Line1"
2909  Xexpr "File2:20:Line2"
2910  Xexpr "File3:30:Line3"
2911  Xolder | Xolder
2912  call assert_equal(3, g:Xgetlist({'nr':'$'}).nr)
2913  call g:Xsetlist([], 'f')
2914
2915  Xexpr "File1:10:Line1"
2916  Xexpr "File2:20:Line2"
2917  Xexpr "File3:30:Line3"
2918  Xolder | Xolder
2919  call g:Xsetlist([], 'a', {'nr':'$', 'title':'Compiler'})
2920  call assert_equal('Compiler', g:Xgetlist({'nr':3, 'all':1}).title)
2921endfunc
2922
2923func Test_Qf_Size()
2924  call XsizeTests('c')
2925  call XsizeTests('l')
2926endfunc
2927
2928func Test_cclose_from_copen()
2929    augroup QF_Test
2930	au!
2931        au FileType qf :call assert_fails(':cclose', 'E788')
2932    augroup END
2933    copen
2934    augroup QF_Test
2935	au!
2936    augroup END
2937    augroup! QF_Test
2938endfunc
2939
2940func Test_cclose_in_autocmd()
2941  " Problem is only triggered if "starting" is zero, so that the OptionsSet
2942  " event will be triggered.
2943  call test_override('starting', 1)
2944  augroup QF_Test
2945    au!
2946    au FileType qf :call assert_fails(':cclose', 'E788')
2947  augroup END
2948  copen
2949  augroup QF_Test
2950    au!
2951  augroup END
2952  augroup! QF_Test
2953  call test_override('starting', 0)
2954endfunc
2955
2956" Check that ":file" without an argument is possible even when "curbuf_lock"
2957" is set.
2958func Test_file_from_copen()
2959  " Works without argument.
2960  augroup QF_Test
2961    au!
2962    au FileType qf file
2963  augroup END
2964  copen
2965
2966  augroup QF_Test
2967    au!
2968  augroup END
2969  cclose
2970
2971  " Fails with argument.
2972  augroup QF_Test
2973    au!
2974    au FileType qf call assert_fails(':file foo', 'E788')
2975  augroup END
2976  copen
2977  augroup QF_Test
2978    au!
2979  augroup END
2980  cclose
2981
2982  augroup! QF_Test
2983endfunc
2984
2985func Test_resize_from_copen()
2986    augroup QF_Test
2987	au!
2988        au FileType qf resize 5
2989    augroup END
2990    try
2991	" This should succeed without any exception.  No other buffers are
2992	" involved in the autocmd.
2993	copen
2994    finally
2995	augroup QF_Test
2996	    au!
2997	augroup END
2998	augroup! QF_Test
2999    endtry
3000endfunc
3001
3002" Tests for the quickfix buffer b:changedtick variable
3003func Xchangedtick_tests(cchar)
3004  call s:setup_commands(a:cchar)
3005
3006  new | only
3007
3008  Xexpr "" | Xexpr "" | Xexpr ""
3009
3010  Xopen
3011  Xolder
3012  Xolder
3013  Xaddexpr "F1:10:Line10"
3014  Xaddexpr "F2:20:Line20"
3015  call g:Xsetlist([{"filename":"F3", "lnum":30, "text":"Line30"}], 'a')
3016  call g:Xsetlist([], 'f')
3017  call assert_equal(8, getbufvar('%', 'changedtick'))
3018  Xclose
3019endfunc
3020
3021func Test_changedtick()
3022  call Xchangedtick_tests('c')
3023  call Xchangedtick_tests('l')
3024endfunc
3025
3026" Tests for parsing an expression using setqflist()
3027func Xsetexpr_tests(cchar)
3028  call s:setup_commands(a:cchar)
3029
3030  let t = ["File1:10:Line10", "File1:20:Line20"]
3031  call g:Xsetlist([], ' ', {'lines' : t})
3032  call g:Xsetlist([], 'a', {'lines' : ["File1:30:Line30"]})
3033
3034  let l = g:Xgetlist()
3035  call assert_equal(3, len(l))
3036  call assert_equal(20, l[1].lnum)
3037  call assert_equal('Line30', l[2].text)
3038  call g:Xsetlist([], 'r', {'lines' : ["File2:5:Line5"]})
3039  let l = g:Xgetlist()
3040  call assert_equal(1, len(l))
3041  call assert_equal('Line5', l[0].text)
3042  call assert_equal(-1, g:Xsetlist([], 'a', {'lines' : 10}))
3043  call assert_equal(-1, g:Xsetlist([], 'a', {'lines' : "F1:10:L10"}))
3044
3045  call g:Xsetlist([], 'f')
3046  " Add entries to multiple lists
3047  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["File1:10:Line10"]})
3048  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["File2:20:Line20"]})
3049  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["File1:15:Line15"]})
3050  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["File2:25:Line25"]})
3051  call assert_equal('Line15', g:Xgetlist({'nr':1, 'items':1}).items[1].text)
3052  call assert_equal('Line25', g:Xgetlist({'nr':2, 'items':1}).items[1].text)
3053
3054  " Adding entries using a custom efm
3055  set efm&
3056  call g:Xsetlist([], ' ', {'efm' : '%f#%l#%m',
3057				\ 'lines' : ["F1#10#L10", "F2#20#L20"]})
3058  call assert_equal(20, g:Xgetlist({'items':1}).items[1].lnum)
3059  call g:Xsetlist([], 'a', {'efm' : '%f#%l#%m', 'lines' : ["F3:30:L30"]})
3060  call assert_equal('F3:30:L30', g:Xgetlist({'items':1}).items[2].text)
3061  call assert_equal(20, g:Xgetlist({'items':1}).items[1].lnum)
3062  call assert_equal(-1, g:Xsetlist([], 'a', {'efm' : [],
3063				\ 'lines' : ['F1:10:L10']}))
3064endfunc
3065
3066func Test_setexpr()
3067  call Xsetexpr_tests('c')
3068  call Xsetexpr_tests('l')
3069endfunc
3070
3071" Tests for per quickfix/location list directory stack
3072func Xmultidirstack_tests(cchar)
3073  call s:setup_commands(a:cchar)
3074
3075  call g:Xsetlist([], 'f')
3076  Xexpr "" | Xexpr ""
3077
3078  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["Entering dir 'Xone/a'"]})
3079  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["Entering dir 'Xtwo/a'"]})
3080  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["one.txt:3:one one one"]})
3081  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["two.txt:5:two two two"]})
3082
3083  let l1 = g:Xgetlist({'nr':1, 'items':1})
3084  let l2 = g:Xgetlist({'nr':2, 'items':1})
3085  call assert_equal('Xone/a/one.txt', bufname(l1.items[1].bufnr))
3086  call assert_equal(3, l1.items[1].lnum)
3087  call assert_equal('Xtwo/a/two.txt', bufname(l2.items[1].bufnr))
3088  call assert_equal(5, l2.items[1].lnum)
3089endfunc
3090
3091func Test_multidirstack()
3092  call mkdir('Xone/a', 'p')
3093  call mkdir('Xtwo/a', 'p')
3094  let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7']
3095  call writefile(lines, 'Xone/a/one.txt')
3096  call writefile(lines, 'Xtwo/a/two.txt')
3097  let save_efm = &efm
3098  set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f'
3099
3100  call Xmultidirstack_tests('c')
3101  call Xmultidirstack_tests('l')
3102
3103  let &efm = save_efm
3104  call delete('Xone', 'rf')
3105  call delete('Xtwo', 'rf')
3106endfunc
3107
3108" Tests for per quickfix/location list file stack
3109func Xmultifilestack_tests(cchar)
3110  call s:setup_commands(a:cchar)
3111
3112  call g:Xsetlist([], 'f')
3113  Xexpr "" | Xexpr ""
3114
3115  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["[one.txt]"]})
3116  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["[two.txt]"]})
3117  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["(3,5) one one one"]})
3118  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["(5,9) two two two"]})
3119
3120  let l1 = g:Xgetlist({'nr':1, 'items':1})
3121  let l2 = g:Xgetlist({'nr':2, 'items':1})
3122  call assert_equal('one.txt', bufname(l1.items[1].bufnr))
3123  call assert_equal(3, l1.items[1].lnum)
3124  call assert_equal('two.txt', bufname(l2.items[1].bufnr))
3125  call assert_equal(5, l2.items[1].lnum)
3126
3127  " Test for start of a new error line in the same line where a previous
3128  " error line ends with a file stack.
3129  let efm_val = 'Error\ l%l\ in\ %f,'
3130  let efm_val .= '%-P%>(%f%r,Error\ l%l\ in\ %m,%-Q)%r'
3131  let l = g:Xgetlist({'lines' : [
3132	      \ '(one.txt',
3133	      \ 'Error l4 in one.txt',
3134	      \ ') (two.txt',
3135	      \ 'Error l6 in two.txt',
3136	      \ ')',
3137	      \ 'Error l8 in one.txt'
3138	      \ ], 'efm' : efm_val})
3139  call assert_equal(3, len(l.items))
3140  call assert_equal('one.txt', bufname(l.items[0].bufnr))
3141  call assert_equal(4, l.items[0].lnum)
3142  call assert_equal('one.txt', l.items[0].text)
3143  call assert_equal('two.txt', bufname(l.items[1].bufnr))
3144  call assert_equal(6, l.items[1].lnum)
3145  call assert_equal('two.txt', l.items[1].text)
3146  call assert_equal('one.txt', bufname(l.items[2].bufnr))
3147  call assert_equal(8, l.items[2].lnum)
3148  call assert_equal('', l.items[2].text)
3149endfunc
3150
3151func Test_multifilestack()
3152  let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7']
3153  call writefile(lines, 'one.txt')
3154  call writefile(lines, 'two.txt')
3155  let save_efm = &efm
3156  set efm=%+P[%f],(%l\\,%c)\ %m,%-Q
3157
3158  call Xmultifilestack_tests('c')
3159  call Xmultifilestack_tests('l')
3160
3161  let &efm = save_efm
3162  call delete('one.txt')
3163  call delete('two.txt')
3164endfunc
3165
3166" Tests for per buffer 'efm' setting
3167func Test_perbuf_efm()
3168  call writefile(["File1-10-Line10"], 'one.txt')
3169  call writefile(["File2#20#Line20"], 'two.txt')
3170  set efm=%f#%l#%m
3171  new | only
3172  new
3173  setlocal efm=%f-%l-%m
3174  cfile one.txt
3175  wincmd w
3176  caddfile two.txt
3177
3178  let l = getqflist()
3179  call assert_equal(10, l[0].lnum)
3180  call assert_equal('Line20', l[1].text)
3181
3182  set efm&
3183  new | only
3184  call delete('one.txt')
3185  call delete('two.txt')
3186endfunc
3187
3188" Open multiple help windows using ":lhelpgrep
3189" This test used to crash Vim
3190func Test_Multi_LL_Help()
3191    new | only
3192    lhelpgrep window
3193    lopen
3194    e#
3195    lhelpgrep buffer
3196    call assert_equal(3, winnr('$'))
3197    call assert_true(len(getloclist(1)) != 0)
3198    call assert_true(len(getloclist(2)) != 0)
3199    new | only
3200endfunc
3201
3202" Tests for adding new quickfix lists using setqflist()
3203func XaddQf_tests(cchar)
3204  call s:setup_commands(a:cchar)
3205
3206  " Create a new list using ' ' for action
3207  call g:Xsetlist([], 'f')
3208  call g:Xsetlist([], ' ', {'title' : 'Test1'})
3209  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3210  call assert_equal(1, l.nr)
3211  call assert_equal('Test1', l.title)
3212
3213  " Create a new list using ' ' for action and '$' for 'nr'
3214  call g:Xsetlist([], 'f')
3215  call g:Xsetlist([], ' ', {'title' : 'Test2', 'nr' : '$'})
3216  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3217  call assert_equal(1, l.nr)
3218  call assert_equal('Test2', l.title)
3219
3220  " Create a new list using 'a' for action
3221  call g:Xsetlist([], 'f')
3222  call g:Xsetlist([], 'a', {'title' : 'Test3'})
3223  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3224  call assert_equal(1, l.nr)
3225  call assert_equal('Test3', l.title)
3226
3227  " Create a new list using 'a' for action and '$' for 'nr'
3228  call g:Xsetlist([], 'f')
3229  call g:Xsetlist([], 'a', {'title' : 'Test3', 'nr' : '$'})
3230  call g:Xsetlist([], 'a', {'title' : 'Test4'})
3231  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3232  call assert_equal(1, l.nr)
3233  call assert_equal('Test4', l.title)
3234
3235  " Adding a quickfix list should remove all the lists following the current
3236  " list.
3237  Xexpr "" | Xexpr "" | Xexpr ""
3238  silent! 10Xolder
3239  call g:Xsetlist([], ' ', {'title' : 'Test5'})
3240  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3241  call assert_equal(2, l.nr)
3242  call assert_equal('Test5', l.title)
3243
3244  " Add a quickfix list using '$' as the list number.
3245  let lastqf = g:Xgetlist({'nr':'$'}).nr
3246  silent! 99Xolder
3247  call g:Xsetlist([], ' ', {'nr' : '$', 'title' : 'Test6'})
3248  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3249  call assert_equal(lastqf + 1, l.nr)
3250  call assert_equal('Test6', l.title)
3251
3252  " Add a quickfix list using 'nr' set to one more than the quickfix
3253  " list size.
3254  let lastqf = g:Xgetlist({'nr':'$'}).nr
3255  silent! 99Xolder
3256  call g:Xsetlist([], ' ', {'nr' : lastqf + 1, 'title' : 'Test7'})
3257  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3258  call assert_equal(lastqf + 1, l.nr)
3259  call assert_equal('Test7', l.title)
3260
3261  " Add a quickfix list to a stack with 10 lists using 'nr' set to '$'
3262  exe repeat('Xexpr "" |', 9) . 'Xexpr ""'
3263  silent! 99Xolder
3264  call g:Xsetlist([], ' ', {'nr' : '$', 'title' : 'Test8'})
3265  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3266  call assert_equal(10, l.nr)
3267  call assert_equal('Test8', l.title)
3268
3269  " Add a quickfix list using 'nr' set to a value greater than 10
3270  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : 12, 'title' : 'Test9'}))
3271
3272  " Try adding a quickfix list with 'nr' set to a value greater than the
3273  " quickfix list size but less than 10.
3274  call g:Xsetlist([], 'f')
3275  Xexpr "" | Xexpr "" | Xexpr ""
3276  silent! 99Xolder
3277  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : 8, 'title' : 'Test10'}))
3278
3279  " Add a quickfix list using 'nr' set to a some string or list
3280  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : [1,2], 'title' : 'Test11'}))
3281endfunc
3282
3283func Test_add_qf()
3284  call XaddQf_tests('c')
3285  call XaddQf_tests('l')
3286endfunc
3287
3288" Test for getting the quickfix list items from some text without modifying
3289" the quickfix stack
3290func XgetListFromLines(cchar)
3291  call s:setup_commands(a:cchar)
3292  call g:Xsetlist([], 'f')
3293
3294  let l = g:Xgetlist({'lines' : ["File2:20:Line20", "File2:30:Line30"]}).items
3295  call assert_equal(2, len(l))
3296  call assert_equal(30, l[1].lnum)
3297
3298  call assert_equal({}, g:Xgetlist({'lines' : 10}))
3299  call assert_equal({}, g:Xgetlist({'lines' : 'File1:10:Line10'}))
3300  call assert_equal([], g:Xgetlist({'lines' : []}).items)
3301  call assert_equal([], g:Xgetlist({'lines' : [10, 20]}).items)
3302
3303  " Parse text using a custom efm
3304  set efm&
3305  let l = g:Xgetlist({'lines':['File3#30#Line30'], 'efm' : '%f#%l#%m'}).items
3306  call assert_equal('Line30', l[0].text)
3307  let l = g:Xgetlist({'lines':['File3:30:Line30'], 'efm' : '%f-%l-%m'}).items
3308  call assert_equal('File3:30:Line30', l[0].text)
3309  let l = g:Xgetlist({'lines':['File3:30:Line30'], 'efm' : [1,2]})
3310  call assert_equal({}, l)
3311  call assert_fails("call g:Xgetlist({'lines':['abc'], 'efm':'%2'})", 'E376:')
3312  call assert_fails("call g:Xgetlist({'lines':['abc'], 'efm':''})", 'E378:')
3313
3314  " Make sure that the quickfix stack is not modified
3315  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
3316endfunc
3317
3318func Test_get_list_from_lines()
3319  call XgetListFromLines('c')
3320  call XgetListFromLines('l')
3321endfunc
3322
3323" Tests for the quickfix list id
3324func Xqfid_tests(cchar)
3325  call s:setup_commands(a:cchar)
3326
3327  call g:Xsetlist([], 'f')
3328  call assert_equal(0, g:Xgetlist({'id':0}).id)
3329  Xexpr ''
3330  let start_id = g:Xgetlist({'id' : 0}).id
3331  Xexpr '' | Xexpr ''
3332  Xolder
3333  call assert_equal(start_id, g:Xgetlist({'id':0, 'nr':1}).id)
3334  call assert_equal(start_id + 1, g:Xgetlist({'id':0, 'nr':0}).id)
3335  call assert_equal(start_id + 2, g:Xgetlist({'id':0, 'nr':'$'}).id)
3336  call assert_equal(0, g:Xgetlist({'id':0, 'nr':99}).id)
3337  call assert_equal(2, g:Xgetlist({'id':start_id + 1, 'nr':0}).nr)
3338  call assert_equal(0, g:Xgetlist({'id':99, 'nr':0}).id)
3339  call assert_equal(0, g:Xgetlist({'id':"abc", 'nr':0}).id)
3340
3341  call g:Xsetlist([], 'a', {'id':start_id, 'context':[1,2]})
3342  call assert_equal([1,2], g:Xgetlist({'nr':1, 'context':1}).context)
3343  call g:Xsetlist([], 'a', {'id':start_id+1, 'lines':['F1:10:L10']})
3344  call assert_equal('L10', g:Xgetlist({'nr':2, 'items':1}).items[0].text)
3345  call assert_equal(-1, g:Xsetlist([], 'a', {'id':999, 'title':'Vim'}))
3346  call assert_equal(-1, g:Xsetlist([], 'a', {'id':'abc', 'title':'Vim'}))
3347
3348  let qfid = g:Xgetlist({'id':0, 'nr':0})
3349  call g:Xsetlist([], 'f')
3350  call assert_equal(0, g:Xgetlist({'id':qfid, 'nr':0}).id)
3351endfunc
3352
3353func Test_qf_id()
3354  call Xqfid_tests('c')
3355  call Xqfid_tests('l')
3356endfunc
3357
3358func Xqfjump_tests(cchar)
3359  call s:setup_commands(a:cchar)
3360
3361  call writefile(["Line1\tFoo", "Line2"], 'F1')
3362  call writefile(["Line1\tBar", "Line2"], 'F2')
3363  call writefile(["Line1\tBaz", "Line2"], 'F3')
3364
3365  call g:Xsetlist([], 'f')
3366
3367  " Tests for
3368  "   Jumping to a line using a pattern
3369  "   Jumping to a column greater than the last column in a line
3370  "   Jumping to a line greater than the last line in the file
3371  let l = []
3372  for i in range(1, 7)
3373    call add(l, {})
3374  endfor
3375  let l[0].filename='F1'
3376  let l[0].pattern='Line1'
3377  let l[1].filename='F2'
3378  let l[1].pattern='Line1'
3379  let l[2].filename='F3'
3380  let l[2].pattern='Line1'
3381  let l[3].filename='F3'
3382  let l[3].lnum=1
3383  let l[3].col=9
3384  let l[3].vcol=1
3385  let l[4].filename='F3'
3386  let l[4].lnum=99
3387  let l[5].filename='F3'
3388  let l[5].lnum=1
3389  let l[5].col=99
3390  let l[5].vcol=1
3391  let l[6].filename='F3'
3392  let l[6].pattern='abcxyz'
3393
3394  call g:Xsetlist([], ' ', {'items' : l})
3395  Xopen | only
3396  2Xnext
3397  call assert_equal(3, g:Xgetlist({'idx' : 0}).idx)
3398  call assert_equal('F3', bufname('%'))
3399  Xnext
3400  call assert_equal(7, col('.'))
3401  Xnext
3402  call assert_equal(2, line('.'))
3403  Xnext
3404  call assert_equal(9, col('.'))
3405  2
3406  Xnext
3407  call assert_equal(2, line('.'))
3408
3409  if a:cchar == 'l'
3410    " When jumping to a location list entry in the location list window and
3411    " no usable windows are available, then a new window should be opened.
3412    enew! | new | only
3413    call g:Xsetlist([], 'f')
3414    setlocal buftype=nofile
3415    new
3416    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']})
3417    Xopen
3418    let winid = win_getid()
3419    wincmd p
3420    close
3421    call win_gotoid(winid)
3422    Xnext
3423    call assert_equal(3, winnr('$'))
3424    call assert_equal(1, winnr())
3425    call assert_equal(2, line('.'))
3426
3427    " When jumping to an entry in the location list window and the window
3428    " associated with the location list is not present and a window containing
3429    " the file is already present, then that window should be used.
3430    close
3431    belowright new
3432    call g:Xsetlist([], 'f')
3433    edit F3
3434    call win_gotoid(winid)
3435    Xlast
3436    call assert_equal(3, winnr())
3437    call assert_equal(6, g:Xgetlist({'size' : 1}).size)
3438    call assert_equal(winid, g:Xgetlist({'winid' : 1}).winid)
3439  endif
3440
3441  " Cleanup
3442  enew!
3443  new | only
3444
3445  call delete('F1')
3446  call delete('F2')
3447  call delete('F3')
3448endfunc
3449
3450func Test_qfjump()
3451  call Xqfjump_tests('c')
3452  call Xqfjump_tests('l')
3453endfunc
3454
3455" Tests for the getqflist() and getloclist() functions when the list is not
3456" present or is empty
3457func Xgetlist_empty_tests(cchar)
3458  call s:setup_commands(a:cchar)
3459
3460  " Empty quickfix stack
3461  call g:Xsetlist([], 'f')
3462  call assert_equal('', g:Xgetlist({'context' : 0}).context)
3463  call assert_equal(0, g:Xgetlist({'id' : 0}).id)
3464  call assert_equal(0, g:Xgetlist({'idx' : 0}).idx)
3465  call assert_equal([], g:Xgetlist({'items' : 0}).items)
3466  call assert_equal(0, g:Xgetlist({'nr' : 0}).nr)
3467  call assert_equal(0, g:Xgetlist({'size' : 0}).size)
3468  call assert_equal('', g:Xgetlist({'title' : 0}).title)
3469  call assert_equal(0, g:Xgetlist({'winid' : 0}).winid)
3470  call assert_equal(0, g:Xgetlist({'changedtick' : 0}).changedtick)
3471  if a:cchar == 'c'
3472    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0,
3473		  \ 'items' : [], 'nr' : 0, 'size' : 0, 'qfbufnr' : 0,
3474		  \ 'title' : '', 'winid' : 0, 'changedtick': 0},
3475		  \ g:Xgetlist({'all' : 0}))
3476  else
3477    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0,
3478		\ 'items' : [], 'nr' : 0, 'size' : 0, 'title' : '',
3479		\ 'winid' : 0, 'changedtick': 0, 'filewinid' : 0,
3480		\ 'qfbufnr' : 0},
3481		\ g:Xgetlist({'all' : 0}))
3482  endif
3483
3484  " Quickfix window with empty stack
3485  silent! Xopen
3486  let qfwinid = (a:cchar == 'c') ? win_getid() : 0
3487  let qfbufnr = (a:cchar == 'c') ? bufnr('') : 0
3488  call assert_equal(qfwinid, g:Xgetlist({'winid' : 0}).winid)
3489  Xclose
3490
3491  " Empty quickfix list
3492  Xexpr ""
3493  call assert_equal('', g:Xgetlist({'context' : 0}).context)
3494  call assert_notequal(0, g:Xgetlist({'id' : 0}).id)
3495  call assert_equal(0, g:Xgetlist({'idx' : 0}).idx)
3496  call assert_equal([], g:Xgetlist({'items' : 0}).items)
3497  call assert_notequal(0, g:Xgetlist({'nr' : 0}).nr)
3498  call assert_equal(0, g:Xgetlist({'size' : 0}).size)
3499  call assert_notequal('', g:Xgetlist({'title' : 0}).title)
3500  call assert_equal(0, g:Xgetlist({'winid' : 0}).winid)
3501  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3502
3503  let qfid = g:Xgetlist({'id' : 0}).id
3504  call g:Xsetlist([], 'f')
3505
3506  " Non-existing quickfix identifier
3507  call assert_equal('', g:Xgetlist({'id' : qfid, 'context' : 0}).context)
3508  call assert_equal(0, g:Xgetlist({'id' : qfid}).id)
3509  call assert_equal(0, g:Xgetlist({'id' : qfid, 'idx' : 0}).idx)
3510  call assert_equal([], g:Xgetlist({'id' : qfid, 'items' : 0}).items)
3511  call assert_equal(0, g:Xgetlist({'id' : qfid, 'nr' : 0}).nr)
3512  call assert_equal(0, g:Xgetlist({'id' : qfid, 'size' : 0}).size)
3513  call assert_equal('', g:Xgetlist({'id' : qfid, 'title' : 0}).title)
3514  call assert_equal(0, g:Xgetlist({'id' : qfid, 'winid' : 0}).winid)
3515  call assert_equal(0, g:Xgetlist({'id' : qfid, 'changedtick' : 0}).changedtick)
3516  if a:cchar == 'c'
3517    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
3518		\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
3519		\ 'qfbufnr' : qfbufnr,
3520		\ 'changedtick' : 0}, g:Xgetlist({'id' : qfid, 'all' : 0}))
3521  else
3522    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
3523		\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
3524		\ 'changedtick' : 0, 'filewinid' : 0, 'qfbufnr' : 0},
3525		\ g:Xgetlist({'id' : qfid, 'all' : 0}))
3526  endif
3527
3528  " Non-existing quickfix list number
3529  call assert_equal('', g:Xgetlist({'nr' : 5, 'context' : 0}).context)
3530  call assert_equal(0, g:Xgetlist({'nr' : 5}).nr)
3531  call assert_equal(0, g:Xgetlist({'nr' : 5, 'idx' : 0}).idx)
3532  call assert_equal([], g:Xgetlist({'nr' : 5, 'items' : 0}).items)
3533  call assert_equal(0, g:Xgetlist({'nr' : 5, 'id' : 0}).id)
3534  call assert_equal(0, g:Xgetlist({'nr' : 5, 'size' : 0}).size)
3535  call assert_equal('', g:Xgetlist({'nr' : 5, 'title' : 0}).title)
3536  call assert_equal(0, g:Xgetlist({'nr' : 5, 'winid' : 0}).winid)
3537  call assert_equal(0, g:Xgetlist({'nr' : 5, 'changedtick' : 0}).changedtick)
3538  if a:cchar == 'c'
3539    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
3540		\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
3541		\ 'changedtick' : 0, 'qfbufnr' : qfbufnr},
3542		\ g:Xgetlist({'nr' : 5, 'all' : 0}))
3543  else
3544    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
3545		\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
3546		\ 'changedtick' : 0, 'filewinid' : 0, 'qfbufnr' : 0},
3547		\ g:Xgetlist({'nr' : 5, 'all' : 0}))
3548  endif
3549endfunc
3550
3551func Test_getqflist()
3552  call Xgetlist_empty_tests('c')
3553  call Xgetlist_empty_tests('l')
3554endfunc
3555
3556func Test_getqflist_invalid_nr()
3557  " The following commands used to crash Vim
3558  cexpr ""
3559  call getqflist({'nr' : $XXX_DOES_NOT_EXIST_XXX})
3560
3561  " Cleanup
3562  call setqflist([], 'r')
3563endfunc
3564
3565" Tests for the quickfix/location list changedtick
3566func Xqftick_tests(cchar)
3567  call s:setup_commands(a:cchar)
3568
3569  call g:Xsetlist([], 'f')
3570
3571  Xexpr "F1:10:Line10"
3572  let qfid = g:Xgetlist({'id' : 0}).id
3573  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3574  Xaddexpr "F2:20:Line20\nF2:21:Line21"
3575  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
3576  call g:Xsetlist([], 'a', {'lines' : ["F3:30:Line30", "F3:31:Line31"]})
3577  call assert_equal(3, g:Xgetlist({'changedtick' : 0}).changedtick)
3578  call g:Xsetlist([], 'r', {'lines' : ["F4:40:Line40"]})
3579  call assert_equal(4, g:Xgetlist({'changedtick' : 0}).changedtick)
3580  call g:Xsetlist([], 'a', {'title' : 'New Title'})
3581  call assert_equal(5, g:Xgetlist({'changedtick' : 0}).changedtick)
3582
3583  enew!
3584  call append(0, ["F5:50:L50", "F6:60:L60"])
3585  Xaddbuffer
3586  call assert_equal(6, g:Xgetlist({'changedtick' : 0}).changedtick)
3587  enew!
3588
3589  call g:Xsetlist([], 'a', {'context' : {'bus' : 'pci'}})
3590  call assert_equal(7, g:Xgetlist({'changedtick' : 0}).changedtick)
3591  call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'},
3592	      \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], 'a')
3593  call assert_equal(8, g:Xgetlist({'changedtick' : 0}).changedtick)
3594  call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'},
3595	      \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], ' ')
3596  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3597  call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'},
3598	      \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], 'r')
3599  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
3600
3601  call writefile(["F8:80:L80", "F8:81:L81"], "Xone")
3602  Xfile Xone
3603  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3604  Xaddfile Xone
3605  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
3606
3607  " Test case for updating a non-current quickfix list
3608  call g:Xsetlist([], 'f')
3609  Xexpr "F1:1:L1"
3610  Xexpr "F2:2:L2"
3611  call g:Xsetlist([], 'a', {'nr' : 1, "lines" : ["F10:10:L10"]})
3612  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3613  call assert_equal(2, g:Xgetlist({'nr' : 1, 'changedtick' : 0}).changedtick)
3614
3615  call delete("Xone")
3616endfunc
3617
3618func Test_qf_tick()
3619  call Xqftick_tests('c')
3620  call Xqftick_tests('l')
3621endfunc
3622
3623" Test helpgrep with lang specifier
3624func Xtest_helpgrep_with_lang_specifier(cchar)
3625  call s:setup_commands(a:cchar)
3626  Xhelpgrep Vim@en
3627  call assert_equal('help', &filetype)
3628  call assert_notequal(0, g:Xgetlist({'nr' : '$'}).nr)
3629  new | only
3630endfunc
3631
3632func Test_helpgrep_with_lang_specifier()
3633  call Xtest_helpgrep_with_lang_specifier('c')
3634  call Xtest_helpgrep_with_lang_specifier('l')
3635endfunc
3636
3637" The following test used to crash Vim.
3638" Open the location list window and close the regular window associated with
3639" the location list. When the garbage collection runs now, it incorrectly
3640" marks the location list context as not in use and frees the context.
3641func Test_ll_window_ctx()
3642  call setloclist(0, [], 'f')
3643  call setloclist(0, [], 'a', {'context' : []})
3644  lopen | only
3645  call test_garbagecollect_now()
3646  echo getloclist(0, {'context' : 1}).context
3647  enew | only
3648endfunc
3649
3650" The following test used to crash vim
3651func Test_lfile_crash()
3652  sp Xtest
3653  au QuickFixCmdPre * bw
3654  call assert_fails('lfile', 'E40')
3655  au! QuickFixCmdPre
3656endfunc
3657
3658" The following test used to crash vim
3659func Test_lbuffer_crash()
3660  sv Xtest
3661  augroup QF_Test
3662    au!
3663    au * * bw
3664  augroup END
3665  lbuffer
3666  augroup QF_Test
3667    au!
3668  augroup END
3669endfunc
3670
3671" The following test used to crash vim
3672func Test_lexpr_crash()
3673  augroup QF_Test
3674    au!
3675    au * * call setloclist(0, [], 'f')
3676  augroup END
3677  lexpr ""
3678  augroup QF_Test
3679    au!
3680  augroup END
3681
3682  enew | only
3683  augroup QF_Test
3684    au!
3685    au BufNew * call setloclist(0, [], 'f')
3686  augroup END
3687  lexpr 'x:1:x'
3688  augroup QF_Test
3689    au!
3690  augroup END
3691
3692  enew | only
3693  lexpr ''
3694  lopen
3695  augroup QF_Test
3696    au!
3697    au FileType * call setloclist(0, [], 'f')
3698  augroup END
3699  lexpr ''
3700  augroup QF_Test
3701    au!
3702  augroup END
3703endfunc
3704
3705" The following test used to crash Vim
3706func Test_lvimgrep_crash()
3707  sv Xtest
3708  augroup QF_Test
3709    au!
3710    au * * call setloclist(0, [], 'f')
3711  augroup END
3712  lvimgrep quickfix test_quickfix.vim
3713  augroup QF_Test
3714    au!
3715  augroup END
3716
3717  new | only
3718  augroup QF_Test
3719    au!
3720    au BufEnter * call setloclist(0, [], 'r')
3721  augroup END
3722  call assert_fails('lvimgrep Test_lvimgrep_crash *', 'E926:')
3723  augroup QF_Test
3724    au!
3725  augroup END
3726
3727  enew | only
3728endfunc
3729
3730func Test_lvimgrep_crash2()
3731  au BufNewFile x sfind
3732  call assert_fails('lvimgrep x x', 'E480:')
3733  call assert_fails('lvimgrep x x x', 'E480:')
3734
3735  au! BufNewFile
3736endfunc
3737
3738" Test for the position of the quickfix and location list window
3739func Test_qfwin_pos()
3740  " Open two windows
3741  new | only
3742  new
3743  cexpr ['F1:10:L10']
3744  copen
3745  " Quickfix window should be the bottom most window
3746  call assert_equal(3, winnr())
3747  close
3748  " Open at the very top
3749  wincmd t
3750  topleft copen
3751  call assert_equal(1, winnr())
3752  close
3753  " open left of the current window
3754  wincmd t
3755  below new
3756  leftabove copen
3757  call assert_equal(2, winnr())
3758  close
3759  " open right of the current window
3760  rightbelow copen
3761  call assert_equal(3, winnr())
3762  close
3763endfunc
3764
3765" Tests for quickfix/location lists changed by autocommands when
3766" :vimgrep/:lvimgrep commands are running.
3767func Test_vimgrep_autocmd()
3768  call setqflist([], 'f')
3769  call writefile(['stars'], 'Xtest1.txt')
3770  call writefile(['stars'], 'Xtest2.txt')
3771
3772  " Test 1:
3773  " When searching for a pattern using :vimgrep, if the quickfix list is
3774  " changed by an autocmd, the results should be added to the correct quickfix
3775  " list.
3776  autocmd BufRead Xtest2.txt cexpr '' | cexpr ''
3777  silent vimgrep stars Xtest*.txt
3778  call assert_equal(1, getqflist({'nr' : 0}).nr)
3779  call assert_equal(3, getqflist({'nr' : '$'}).nr)
3780  call assert_equal('Xtest2.txt', bufname(getqflist()[1].bufnr))
3781  au! BufRead Xtest2.txt
3782
3783  " Test 2:
3784  " When searching for a pattern using :vimgrep, if the quickfix list is
3785  " freed, then a error should be given.
3786  silent! %bwipe!
3787  call setqflist([], 'f')
3788  autocmd BufRead Xtest2.txt for i in range(10) | cexpr '' | endfor
3789  call assert_fails('vimgrep stars Xtest*.txt', 'E925:')
3790  au! BufRead Xtest2.txt
3791
3792  " Test 3:
3793  " When searching for a pattern using :lvimgrep, if the location list is
3794  " freed, then the command should error out.
3795  silent! %bwipe!
3796  let g:save_winid = win_getid()
3797  autocmd BufRead Xtest2.txt call setloclist(g:save_winid, [], 'f')
3798  call assert_fails('lvimgrep stars Xtest*.txt', 'E926:')
3799  au! BufRead Xtest2.txt
3800
3801  call delete('Xtest1.txt')
3802  call delete('Xtest2.txt')
3803  call setqflist([], 'f')
3804endfunc
3805
3806" Test for an autocmd changing the current directory when running vimgrep
3807func Xvimgrep_autocmd_cd(cchar)
3808  call s:setup_commands(a:cchar)
3809
3810  %bwipe
3811  let save_cwd = getcwd()
3812
3813  augroup QF_Test
3814    au!
3815    autocmd BufRead * silent cd %:p:h
3816  augroup END
3817
3818  10Xvimgrep /vim/ Xdir/**
3819  let l = g:Xgetlist()
3820  call assert_equal('f1.txt', bufname(l[0].bufnr))
3821  call assert_equal('f2.txt', fnamemodify(bufname(l[2].bufnr), ':t'))
3822
3823  augroup QF_Test
3824    au!
3825  augroup END
3826
3827  exe 'cd ' . save_cwd
3828endfunc
3829
3830func Test_vimgrep_autocmd_cd()
3831  call mkdir('Xdir/a', 'p')
3832  call mkdir('Xdir/b', 'p')
3833  call writefile(['a_L1_vim', 'a_L2_vim'], 'Xdir/a/f1.txt')
3834  call writefile(['b_L1_vim', 'b_L2_vim'], 'Xdir/b/f2.txt')
3835  call Xvimgrep_autocmd_cd('c')
3836  call Xvimgrep_autocmd_cd('l')
3837  %bwipe
3838  call delete('Xdir', 'rf')
3839endfunc
3840
3841" The following test used to crash Vim
3842func Test_lhelpgrep_autocmd()
3843  lhelpgrep quickfix
3844  autocmd QuickFixCmdPost * call setloclist(0, [], 'f')
3845  lhelpgrep buffer
3846  call assert_equal('help', &filetype)
3847  call assert_equal(0, getloclist(0, {'nr' : '$'}).nr)
3848  lhelpgrep tabpage
3849  call assert_equal('help', &filetype)
3850  call assert_equal(1, getloclist(0, {'nr' : '$'}).nr)
3851  au! QuickFixCmdPost
3852
3853  new | only
3854  augroup QF_Test
3855    au!
3856    au BufEnter * call setqflist([], 'f')
3857  augroup END
3858  call assert_fails('helpgrep quickfix', 'E925:')
3859  augroup QF_Test
3860    au! BufEnter
3861  augroup END
3862
3863  new | only
3864  augroup QF_Test
3865    au!
3866    au BufEnter * call setqflist([], 'r')
3867  augroup END
3868  call assert_fails('helpgrep quickfix', 'E925:')
3869  augroup QF_Test
3870    au! BufEnter
3871  augroup END
3872
3873  new | only
3874  augroup QF_Test
3875    au!
3876    au BufEnter * call setloclist(0, [], 'r')
3877  augroup END
3878  call assert_fails('lhelpgrep quickfix', 'E926:')
3879  augroup QF_Test
3880    au! BufEnter
3881  augroup END
3882
3883  new | only
3884endfunc
3885
3886" Test for shortening/simplifying the file name when opening the
3887" quickfix window or when displaying the quickfix list
3888func Test_shorten_fname()
3889  if !has('unix')
3890    return
3891  endif
3892  %bwipe
3893  " Create a quickfix list with a absolute path filename
3894  let fname = getcwd() . '/test_quickfix.vim'
3895  call setqflist([], ' ', {'lines':[fname . ":20:Line20"], 'efm':'%f:%l:%m'})
3896  call assert_equal(fname, bufname('test_quickfix.vim'))
3897  " Opening the quickfix window should simplify the file path
3898  cwindow
3899  call assert_equal('test_quickfix.vim', bufname('test_quickfix.vim'))
3900  cclose
3901  %bwipe
3902  " Create a quickfix list with a absolute path filename
3903  call setqflist([], ' ', {'lines':[fname . ":20:Line20"], 'efm':'%f:%l:%m'})
3904  call assert_equal(fname, bufname('test_quickfix.vim'))
3905  " Displaying the quickfix list should simplify the file path
3906  silent! clist
3907  call assert_equal('test_quickfix.vim', bufname('test_quickfix.vim'))
3908endfunc
3909
3910" Quickfix title tests
3911" In the below tests, 'exe "cmd"' is used to invoke the quickfix commands.
3912" Otherwise due to indentation, the title is set with spaces at the beginning
3913" of the command.
3914func Test_qftitle()
3915  call writefile(["F1:1:Line1"], 'Xerr')
3916
3917  " :cexpr
3918  exe "cexpr readfile('Xerr')"
3919  call assert_equal(":cexpr readfile('Xerr')", getqflist({'title' : 1}).title)
3920
3921  " :cgetexpr
3922  exe "cgetexpr readfile('Xerr')"
3923  call assert_equal(":cgetexpr readfile('Xerr')",
3924					\ getqflist({'title' : 1}).title)
3925
3926  " :caddexpr
3927  call setqflist([], 'f')
3928  exe "caddexpr readfile('Xerr')"
3929  call assert_equal(":caddexpr readfile('Xerr')",
3930					\ getqflist({'title' : 1}).title)
3931
3932  " :cbuffer
3933  new Xerr
3934  exe "cbuffer"
3935  call assert_equal(':cbuffer (Xerr)', getqflist({'title' : 1}).title)
3936
3937  " :cgetbuffer
3938  edit Xerr
3939  exe "cgetbuffer"
3940  call assert_equal(':cgetbuffer (Xerr)', getqflist({'title' : 1}).title)
3941
3942  " :caddbuffer
3943  call setqflist([], 'f')
3944  edit Xerr
3945  exe "caddbuffer"
3946  call assert_equal(':caddbuffer (Xerr)', getqflist({'title' : 1}).title)
3947
3948  " :cfile
3949  exe "cfile Xerr"
3950  call assert_equal(':cfile Xerr', getqflist({'title' : 1}).title)
3951
3952  " :cgetfile
3953  exe "cgetfile Xerr"
3954  call assert_equal(':cgetfile Xerr', getqflist({'title' : 1}).title)
3955
3956  " :caddfile
3957  call setqflist([], 'f')
3958  exe "caddfile Xerr"
3959  call assert_equal(':caddfile Xerr', getqflist({'title' : 1}).title)
3960
3961  " :grep
3962  set grepprg=internal
3963  exe "grep F1 Xerr"
3964  call assert_equal(':grep F1 Xerr', getqflist({'title' : 1}).title)
3965
3966  " :grepadd
3967  call setqflist([], 'f')
3968  exe "grepadd F1 Xerr"
3969  call assert_equal(':grepadd F1 Xerr', getqflist({'title' : 1}).title)
3970  set grepprg&vim
3971
3972  " :vimgrep
3973  exe "vimgrep F1 Xerr"
3974  call assert_equal(':vimgrep F1 Xerr', getqflist({'title' : 1}).title)
3975
3976  " :vimgrepadd
3977  call setqflist([], 'f')
3978  exe "vimgrepadd F1 Xerr"
3979  call assert_equal(':vimgrepadd F1 Xerr', getqflist({'title' : 1}).title)
3980
3981  call setqflist(['F1:10:L10'], ' ')
3982  call assert_equal(':setqflist()', getqflist({'title' : 1}).title)
3983
3984  call setqflist([], 'f')
3985  call setqflist(['F1:10:L10'], 'a')
3986  call assert_equal(':setqflist()', getqflist({'title' : 1}).title)
3987
3988  call setqflist([], 'f')
3989  call setqflist(['F1:10:L10'], 'r')
3990  call assert_equal(':setqflist()', getqflist({'title' : 1}).title)
3991
3992  close
3993  call delete('Xerr')
3994
3995  call setqflist([], ' ', {'title' : 'Errors'})
3996  copen
3997  call assert_equal('Errors', w:quickfix_title)
3998  call setqflist([], 'r', {'items' : [{'filename' : 'a.c', 'lnum' : 10}]})
3999  call assert_equal('Errors', w:quickfix_title)
4000  cclose
4001endfunc
4002
4003func Test_lbuffer_with_bwipe()
4004  new
4005  new
4006  augroup nasty
4007    au * * bwipe
4008  augroup END
4009  lbuffer
4010  augroup nasty
4011    au!
4012  augroup END
4013endfunc
4014
4015" Test for an autocmd freeing the quickfix/location list when cexpr/lexpr is
4016" running
4017func Xexpr_acmd_freelist(cchar)
4018  call s:setup_commands(a:cchar)
4019
4020  " This was using freed memory.
4021  augroup nasty
4022    au * * call g:Xsetlist([], 'f')
4023  augroup END
4024  Xexpr "x"
4025  augroup nasty
4026    au!
4027  augroup END
4028endfunc
4029
4030func Test_cexpr_acmd_freelist()
4031  call Xexpr_acmd_freelist('c')
4032  call Xexpr_acmd_freelist('l')
4033endfunc
4034
4035" Test for commands that create a new quickfix/location list and jump to the
4036" first error automatically.
4037func Xjumpto_first_error_test(cchar)
4038  call s:setup_commands(a:cchar)
4039
4040  call s:create_test_file('Xtestfile1')
4041  call s:create_test_file('Xtestfile2')
4042  let l = ['Xtestfile1:2:Line2', 'Xtestfile2:4:Line4']
4043
4044  " Test for cexpr/lexpr
4045  enew
4046  Xexpr l
4047  call assert_equal('Xtestfile1', bufname(''))
4048  call assert_equal(2, line('.'))
4049
4050  " Test for cfile/lfile
4051  enew
4052  call writefile(l, 'Xerr')
4053  Xfile Xerr
4054  call assert_equal('Xtestfile1', bufname(''))
4055  call assert_equal(2, line('.'))
4056
4057  " Test for cbuffer/lbuffer
4058  edit Xerr
4059  Xbuffer
4060  call assert_equal('Xtestfile1', bufname(''))
4061  call assert_equal(2, line('.'))
4062
4063  call delete('Xerr')
4064  call delete('Xtestfile1')
4065  call delete('Xtestfile2')
4066endfunc
4067
4068func Test_jumpto_first_error()
4069  call Xjumpto_first_error_test('c')
4070  call Xjumpto_first_error_test('l')
4071endfunc
4072
4073" Test for a quickfix autocmd changing the quickfix/location list before
4074" jumping to the first error in the new list.
4075func Xautocmd_changelist(cchar)
4076  call s:setup_commands(a:cchar)
4077
4078  " Test for cfile/lfile
4079  call s:create_test_file('Xtestfile1')
4080  call s:create_test_file('Xtestfile2')
4081  Xexpr 'Xtestfile1:2:Line2'
4082  autocmd QuickFixCmdPost * Xolder
4083  call writefile(['Xtestfile2:4:Line4'], 'Xerr')
4084  Xfile Xerr
4085  call assert_equal('Xtestfile2', bufname(''))
4086  call assert_equal(4, line('.'))
4087  autocmd! QuickFixCmdPost
4088
4089  " Test for cbuffer/lbuffer
4090  call g:Xsetlist([], 'f')
4091  Xexpr 'Xtestfile1:2:Line2'
4092  autocmd QuickFixCmdPost * Xolder
4093  call writefile(['Xtestfile2:4:Line4'], 'Xerr')
4094  edit Xerr
4095  Xbuffer
4096  call assert_equal('Xtestfile2', bufname(''))
4097  call assert_equal(4, line('.'))
4098  autocmd! QuickFixCmdPost
4099
4100  " Test for cexpr/lexpr
4101  call g:Xsetlist([], 'f')
4102  Xexpr 'Xtestfile1:2:Line2'
4103  autocmd QuickFixCmdPost * Xolder
4104  Xexpr 'Xtestfile2:4:Line4'
4105  call assert_equal('Xtestfile2', bufname(''))
4106  call assert_equal(4, line('.'))
4107  autocmd! QuickFixCmdPost
4108
4109  " The grepprg may not be set on non-Unix systems
4110  if has('unix')
4111    " Test for grep/lgrep
4112    call g:Xsetlist([], 'f')
4113    Xexpr 'Xtestfile1:2:Line2'
4114    autocmd QuickFixCmdPost * Xolder
4115    silent Xgrep Line5 Xtestfile2
4116    call assert_equal('Xtestfile2', bufname(''))
4117    call assert_equal(5, line('.'))
4118    autocmd! QuickFixCmdPost
4119  endif
4120
4121  " Test for vimgrep/lvimgrep
4122  call g:Xsetlist([], 'f')
4123  Xexpr 'Xtestfile1:2:Line2'
4124  autocmd QuickFixCmdPost * Xolder
4125  silent Xvimgrep Line5 Xtestfile2
4126  call assert_equal('Xtestfile2', bufname(''))
4127  call assert_equal(5, line('.'))
4128  autocmd! QuickFixCmdPost
4129
4130  " Test for autocommands clearing the quickfix list before jumping to the
4131  " first error. This should not result in an error
4132  autocmd QuickFixCmdPost * call g:Xsetlist([], 'r')
4133  let v:errmsg = ''
4134  " Test for cfile/lfile
4135  Xfile Xerr
4136  call assert_true(v:errmsg !~# 'E42:')
4137  " Test for cbuffer/lbuffer
4138  edit Xerr
4139  Xbuffer
4140  call assert_true(v:errmsg !~# 'E42:')
4141  " Test for cexpr/lexpr
4142  Xexpr 'Xtestfile2:4:Line4'
4143  call assert_true(v:errmsg !~# 'E42:')
4144  " Test for grep/lgrep
4145  " The grepprg may not be set on non-Unix systems
4146  if has('unix')
4147    silent Xgrep Line5 Xtestfile2
4148    call assert_true(v:errmsg !~# 'E42:')
4149  endif
4150  " Test for vimgrep/lvimgrep
4151  call assert_fails('silent Xvimgrep Line5 Xtestfile2', 'E480:')
4152  autocmd! QuickFixCmdPost
4153
4154  call delete('Xerr')
4155  call delete('Xtestfile1')
4156  call delete('Xtestfile2')
4157endfunc
4158
4159func Test_autocmd_changelist()
4160  call Xautocmd_changelist('c')
4161  call Xautocmd_changelist('l')
4162endfunc
4163
4164" Tests for the ':filter /pat/ clist' command
4165func Test_filter_clist()
4166  cexpr ['Xfile1:10:10:Line 10', 'Xfile2:15:15:Line 15']
4167  call assert_equal([' 2 Xfile2:15 col 15: Line 15'],
4168			\ split(execute('filter /Line 15/ clist'), "\n"))
4169  call assert_equal([' 1 Xfile1:10 col 10: Line 10'],
4170			\ split(execute('filter /Xfile1/ clist'), "\n"))
4171  call assert_equal([], split(execute('filter /abc/ clist'), "\n"))
4172
4173  call setqflist([{'module' : 'abc', 'pattern' : 'pat1'},
4174			\ {'module' : 'pqr', 'pattern' : 'pat2'}], ' ')
4175  call assert_equal([' 2 pqr:pat2:  '],
4176			\ split(execute('filter /pqr/ clist'), "\n"))
4177  call assert_equal([' 1 abc:pat1:  '],
4178			\ split(execute('filter /pat1/ clist'), "\n"))
4179endfunc
4180
4181" Tests for the "CTRL-W <CR>" command.
4182func Xview_result_split_tests(cchar)
4183  call s:setup_commands(a:cchar)
4184
4185  " Test that "CTRL-W <CR>" in a qf/ll window fails with empty list.
4186  call g:Xsetlist([])
4187  Xopen
4188  let l:win_count = winnr('$')
4189  call assert_fails('execute "normal! \<C-W>\<CR>"', 'E42')
4190  call assert_equal(l:win_count, winnr('$'))
4191  Xclose
4192endfunc
4193
4194func Test_view_result_split()
4195  call Xview_result_split_tests('c')
4196  call Xview_result_split_tests('l')
4197endfunc
4198
4199" Test that :cc sets curswant
4200func Test_curswant()
4201  helpgrep quickfix
4202  normal! llll
4203  1cc
4204  call assert_equal(getcurpos()[4], virtcol('.'))
4205  cclose | helpclose
4206endfunc
4207
4208" Test for opening a file from the quickfix window using CTRL-W <Enter>
4209" doesn't leave an empty buffer around.
4210func Test_splitview()
4211  call s:create_test_file('Xtestfile1')
4212  call s:create_test_file('Xtestfile2')
4213  new | only
4214  let last_bufnr = bufnr('Test_sv_1', 1)
4215  let l = ['Xtestfile1:2:Line2', 'Xtestfile2:4:Line4']
4216  cgetexpr l
4217  copen
4218  let numbufs = len(getbufinfo())
4219  exe "normal \<C-W>\<CR>"
4220  copen
4221  exe "normal j\<C-W>\<CR>"
4222  " Make sure new empty buffers are not created
4223  call assert_equal(numbufs, len(getbufinfo()))
4224  " Creating a new buffer should use the next available buffer number
4225  call assert_equal(last_bufnr + 4, bufnr("Test_sv_2", 1))
4226  bwipe Test_sv_1
4227  bwipe Test_sv_2
4228  new | only
4229
4230  " When split opening files from location list window, make sure that two
4231  " windows doesn't refer to the same location list
4232  lgetexpr l
4233  let locid = getloclist(0, {'id' : 0}).id
4234  lopen
4235  exe "normal \<C-W>\<CR>"
4236  call assert_notequal(locid, getloclist(0, {'id' : 0}).id)
4237  call assert_equal(0, getloclist(0, {'winid' : 0}).winid)
4238  new | only
4239
4240  " When split opening files from a helpgrep location list window, a new help
4241  " window should be opened with a copy of the location list.
4242  lhelpgrep window
4243  let locid = getloclist(0, {'id' : 0}).id
4244  lwindow
4245  exe "normal j\<C-W>\<CR>"
4246  call assert_notequal(locid, getloclist(0, {'id' : 0}).id)
4247  call assert_equal(0, getloclist(0, {'winid' : 0}).winid)
4248  new | only
4249
4250  " Using :split or :vsplit from a quickfix window should behave like a :new
4251  " or a :vnew command
4252  copen
4253  split
4254  call assert_equal(3, winnr('$'))
4255  let l = getwininfo()
4256  call assert_equal([0, 0, 1], [l[0].quickfix, l[1].quickfix, l[2].quickfix])
4257  close
4258  copen
4259  vsplit
4260  let l = getwininfo()
4261  call assert_equal([0, 0, 1], [l[0].quickfix, l[1].quickfix, l[2].quickfix])
4262  new | only
4263
4264  call delete('Xtestfile1')
4265  call delete('Xtestfile2')
4266endfunc
4267
4268" Test for parsing entries using visual screen column
4269func Test_viscol()
4270  enew
4271  call writefile(["Col1\tCol2\tCol3"], 'Xfile1')
4272  edit Xfile1
4273
4274  " Use byte offset for column number
4275  set efm&
4276  cexpr "Xfile1:1:5:XX\nXfile1:1:9:YY\nXfile1:1:20:ZZ"
4277  call assert_equal([5, 8], [col('.'), virtcol('.')])
4278  cnext
4279  call assert_equal([9, 12], [col('.'), virtcol('.')])
4280  cnext
4281  call assert_equal([14, 20], [col('.'), virtcol('.')])
4282
4283  " Use screen column offset for column number
4284  set efm=%f:%l:%v:%m
4285  cexpr "Xfile1:1:8:XX\nXfile1:1:12:YY\nXfile1:1:20:ZZ"
4286  call assert_equal([5, 8], [col('.'), virtcol('.')])
4287  cnext
4288  call assert_equal([9, 12], [col('.'), virtcol('.')])
4289  cnext
4290  call assert_equal([14, 20], [col('.'), virtcol('.')])
4291  cexpr "Xfile1:1:6:XX\nXfile1:1:15:YY\nXfile1:1:24:ZZ"
4292  call assert_equal([5, 8], [col('.'), virtcol('.')])
4293  cnext
4294  call assert_equal([10, 16], [col('.'), virtcol('.')])
4295  cnext
4296  call assert_equal([14, 20], [col('.'), virtcol('.')])
4297
4298  enew
4299  call writefile(["Col1\täü\töß\tCol4"], 'Xfile1')
4300
4301  " Use byte offset for column number
4302  set efm&
4303  cexpr "Xfile1:1:8:XX\nXfile1:1:11:YY\nXfile1:1:16:ZZ"
4304  call assert_equal([8, 10], [col('.'), virtcol('.')])
4305  cnext
4306  call assert_equal([11, 17], [col('.'), virtcol('.')])
4307  cnext
4308  call assert_equal([16, 25], [col('.'), virtcol('.')])
4309
4310  " Use screen column offset for column number
4311  set efm=%f:%l:%v:%m
4312  cexpr "Xfile1:1:10:XX\nXfile1:1:17:YY\nXfile1:1:25:ZZ"
4313  call assert_equal([8, 10], [col('.'), virtcol('.')])
4314  cnext
4315  call assert_equal([11, 17], [col('.'), virtcol('.')])
4316  cnext
4317  call assert_equal([16, 25], [col('.'), virtcol('.')])
4318
4319  enew | only
4320  set efm&
4321  call delete('Xfile1')
4322endfunc
4323
4324" Test for the quickfix window buffer
4325func Xqfbuf_test(cchar)
4326  call s:setup_commands(a:cchar)
4327
4328  " Quickfix buffer should be reused across closing and opening a quickfix
4329  " window
4330  Xexpr "F1:10:Line10"
4331  Xopen
4332  let qfbnum = bufnr('')
4333  Xclose
4334  " Even after the quickfix window is closed, the buffer should be loaded
4335  call assert_true(bufloaded(qfbnum))
4336  call assert_true(qfbnum, g:Xgetlist({'qfbufnr' : 0}).qfbufnr)
4337  Xopen
4338  " Buffer should be reused when opening the window again
4339  call assert_equal(qfbnum, bufnr(''))
4340  Xclose
4341
4342  if a:cchar == 'l'
4343    %bwipe
4344    " For a location list, when both the file window and the location list
4345    " window for the list are closed, then the buffer should be freed.
4346    new | only
4347    lexpr "F1:10:Line10"
4348    let wid = win_getid()
4349    lopen
4350    let qfbnum = bufnr('')
4351    call assert_match(qfbnum . ' %a-  "\[Location List]"', execute('ls'))
4352    close
4353    " When the location list window is closed, the buffer name should not
4354    " change to 'Quickfix List'
4355    call assert_match(qfbnum . 'u h-  "\[Location List]"', execute('ls!'))
4356    call assert_true(bufloaded(qfbnum))
4357
4358    " After deleting a location list buffer using ":bdelete", opening the
4359    " location list window should mark the buffer as a location list buffer.
4360    exe "bdelete " . qfbnum
4361    lopen
4362    call assert_equal("quickfix", &buftype)
4363    call assert_equal(1, getwininfo(win_getid(winnr()))[0].loclist)
4364    call assert_equal(wid, getloclist(0, {'filewinid' : 0}).filewinid)
4365    call assert_false(&swapfile)
4366    lclose
4367
4368    " When the location list is cleared for the window, the buffer should be
4369    " removed
4370    call setloclist(0, [], 'f')
4371    call assert_false(bufexists(qfbnum))
4372    call assert_equal(0, getloclist(0, {'qfbufnr' : 0}).qfbufnr)
4373
4374    " When the location list is freed with the location list window open, the
4375    " location list buffer should not be lost. It should be reused when the
4376    " location list is again populated.
4377    lexpr "F1:10:Line10"
4378    lopen
4379    let wid = win_getid()
4380    let qfbnum = bufnr('')
4381    wincmd p
4382    call setloclist(0, [], 'f')
4383    lexpr "F1:10:Line10"
4384    lopen
4385    call assert_equal(wid, win_getid())
4386    call assert_equal(qfbnum, bufnr(''))
4387    lclose
4388
4389    " When the window with the location list is closed, the buffer should be
4390    " removed
4391    new | only
4392    call assert_false(bufexists(qfbnum))
4393  endif
4394endfunc
4395
4396func Test_qfbuf()
4397  call Xqfbuf_test('c')
4398  call Xqfbuf_test('l')
4399endfunc
4400
4401" If there is an autocmd to use only one window, then opening the location
4402" list window used to crash Vim.
4403func Test_winonly_autocmd()
4404  call s:create_test_file('Xtest1')
4405  " Autocmd to show only one Vim window at a time
4406  autocmd WinEnter * only
4407  new
4408  " Load the location list
4409  lexpr "Xtest1:5:Line5\nXtest1:10:Line10\nXtest1:15:Line15"
4410  let loclistid = getloclist(0, {'id' : 0}).id
4411  " Open the location list window. Only this window will be shown and the file
4412  " window is closed.
4413  lopen
4414  call assert_equal(loclistid, getloclist(0, {'id' : 0}).id)
4415  " Jump to an entry in the location list and make sure that the cursor is
4416  " positioned correctly.
4417  ll 3
4418  call assert_equal(loclistid, getloclist(0, {'id' : 0}).id)
4419  call assert_equal('Xtest1', bufname(''))
4420  call assert_equal(15, line('.'))
4421  " Cleanup
4422  autocmd! WinEnter
4423  new | only
4424  call delete('Xtest1')
4425endfunc
4426
4427" Test to make sure that an empty quickfix buffer is not reused for loading
4428" a normal buffer.
4429func Test_empty_qfbuf()
4430  enew | only
4431  call writefile(["Test"], 'Xfile1')
4432  call setqflist([], 'f')
4433  copen | only
4434  let qfbuf = bufnr('')
4435  edit Xfile1
4436  call assert_notequal(qfbuf, bufnr(''))
4437  enew
4438  call delete('Xfile1')
4439endfunc
4440
4441" Test for the :cbelow, :cabove, :lbelow and :labove commands.
4442" And for the :cafter, :cbefore, :lafter and :lbefore commands.
4443func Xtest_below(cchar)
4444  call s:setup_commands(a:cchar)
4445
4446  " No quickfix/location list
4447  call assert_fails('Xbelow', 'E42:')
4448  call assert_fails('Xabove', 'E42:')
4449  call assert_fails('Xbefore', 'E42:')
4450  call assert_fails('Xafter', 'E42:')
4451
4452  " Empty quickfix/location list
4453  call g:Xsetlist([])
4454  call assert_fails('Xbelow', 'E42:')
4455  call assert_fails('Xabove', 'E42:')
4456  call assert_fails('Xbefore', 'E42:')
4457  call assert_fails('Xafter', 'E42:')
4458
4459  call s:create_test_file('X1')
4460  call s:create_test_file('X2')
4461  call s:create_test_file('X3')
4462  call s:create_test_file('X4')
4463
4464  " Invalid entries
4465  edit X1
4466  call g:Xsetlist(["E1", "E2"])
4467  call assert_fails('Xbelow', 'E42:')
4468  call assert_fails('Xabove', 'E42:')
4469  call assert_fails('3Xbelow', 'E42:')
4470  call assert_fails('4Xabove', 'E42:')
4471  call assert_fails('Xbefore', 'E42:')
4472  call assert_fails('Xafter', 'E42:')
4473  call assert_fails('3Xbefore', 'E42:')
4474  call assert_fails('4Xafter', 'E42:')
4475
4476  " Test the commands with various arguments
4477  Xexpr ["X1:5:3:L5", "X2:5:2:L5", "X2:10:3:L10", "X2:15:4:L15", "X3:3:5:L3"]
4478  edit +7 X2
4479  Xabove
4480  call assert_equal(['X2', 5], [bufname(''), line('.')])
4481  call assert_fails('Xabove', 'E553:')
4482  normal 7G
4483  Xbefore
4484  call assert_equal(['X2', 5, 2], [bufname(''), line('.'), col('.')])
4485  call assert_fails('Xbefore', 'E553:')
4486
4487  normal 2j
4488  Xbelow
4489  call assert_equal(['X2', 10], [bufname(''), line('.')])
4490  normal 7G
4491  Xafter
4492  call assert_equal(['X2', 10, 3], [bufname(''), line('.'), col('.')])
4493
4494  " Last error in this file
4495  Xbelow 99
4496  call assert_equal(['X2', 15], [bufname(''), line('.')])
4497  call assert_fails('Xbelow', 'E553:')
4498  normal gg
4499  Xafter 99
4500  call assert_equal(['X2', 15, 4], [bufname(''), line('.'), col('.')])
4501  call assert_fails('Xafter', 'E553:')
4502
4503  " First error in this file
4504  Xabove 99
4505  call assert_equal(['X2', 5], [bufname(''), line('.')])
4506  call assert_fails('Xabove', 'E553:')
4507  normal G
4508  Xbefore 99
4509  call assert_equal(['X2', 5, 2], [bufname(''), line('.'), col('.')])
4510  call assert_fails('Xbefore', 'E553:')
4511
4512  normal gg
4513  Xbelow 2
4514  call assert_equal(['X2', 10], [bufname(''), line('.')])
4515  normal gg
4516  Xafter 2
4517  call assert_equal(['X2', 10, 3], [bufname(''), line('.'), col('.')])
4518
4519  normal G
4520  Xabove 2
4521  call assert_equal(['X2', 10], [bufname(''), line('.')])
4522  normal G
4523  Xbefore 2
4524  call assert_equal(['X2', 10, 3], [bufname(''), line('.'), col('.')])
4525
4526  edit X4
4527  call assert_fails('Xabove', 'E42:')
4528  call assert_fails('Xbelow', 'E42:')
4529  call assert_fails('Xbefore', 'E42:')
4530  call assert_fails('Xafter', 'E42:')
4531  if a:cchar == 'l'
4532    " If a buffer has location list entries from some other window but not
4533    " from the current window, then the commands should fail.
4534    edit X1 | split | call setloclist(0, [], 'f')
4535    call assert_fails('Xabove', 'E776:')
4536    call assert_fails('Xbelow', 'E776:')
4537    call assert_fails('Xbefore', 'E776:')
4538    call assert_fails('Xafter', 'E776:')
4539    close
4540  endif
4541
4542  " Test for lines with multiple quickfix entries
4543  Xexpr ["X1:5:L5", "X2:5:1:L5_1", "X2:5:2:L5_2", "X2:5:3:L5_3",
4544	      \ "X2:10:1:L10_1", "X2:10:2:L10_2", "X2:10:3:L10_3",
4545	      \ "X2:15:1:L15_1", "X2:15:2:L15_2", "X2:15:3:L15_3", "X3:3:L3"]
4546  edit +1 X2
4547  Xbelow 2
4548  call assert_equal(['X2', 10, 1], [bufname(''), line('.'), col('.')])
4549  normal 1G
4550  Xafter 2
4551  call assert_equal(['X2', 5, 2], [bufname(''), line('.'), col('.')])
4552
4553  normal gg
4554  Xbelow 99
4555  call assert_equal(['X2', 15, 1], [bufname(''), line('.'), col('.')])
4556  normal gg
4557  Xafter 99
4558  call assert_equal(['X2', 15, 3], [bufname(''), line('.'), col('.')])
4559
4560  normal G
4561  Xabove 2
4562  call assert_equal(['X2', 10, 1], [bufname(''), line('.'), col('.')])
4563  normal G
4564  Xbefore 2
4565  call assert_equal(['X2', 15, 2], [bufname(''), line('.'), col('.')])
4566
4567  normal G
4568  Xabove 99
4569  call assert_equal(['X2', 5, 1], [bufname(''), line('.'), col('.')])
4570  normal G
4571  Xbefore 99
4572  call assert_equal(['X2', 5, 1], [bufname(''), line('.'), col('.')])
4573
4574  normal 10G
4575  Xabove
4576  call assert_equal(['X2', 5, 1], [bufname(''), line('.'), col('.')])
4577  normal 10G$
4578  2Xbefore
4579  call assert_equal(['X2', 10, 2], [bufname(''), line('.'), col('.')])
4580
4581  normal 10G
4582  Xbelow
4583  call assert_equal(['X2', 15, 1], [bufname(''), line('.'), col('.')])
4584  normal 9G
4585  5Xafter
4586  call assert_equal(['X2', 15, 2], [bufname(''), line('.'), col('.')])
4587
4588  " Invalid range
4589  if a:cchar == 'c'
4590    call assert_fails('-2cbelow', 'E16:')
4591    call assert_fails('-2cafter', 'E16:')
4592  else
4593    call assert_fails('-2lbelow', 'E16:')
4594    call assert_fails('-2lafter', 'E16:')
4595  endif
4596
4597  call delete('X1')
4598  call delete('X2')
4599  call delete('X3')
4600  call delete('X4')
4601endfunc
4602
4603func Test_cbelow()
4604  call Xtest_below('c')
4605  call Xtest_below('l')
4606endfunc
4607
4608func Test_quickfix_count()
4609  let commands = [
4610	\ 'cNext',
4611	\ 'cNfile',
4612	\ 'cabove',
4613	\ 'cbelow',
4614	\ 'cfirst',
4615	\ 'clast',
4616	\ 'cnewer',
4617	\ 'cnext',
4618	\ 'cnfile',
4619	\ 'colder',
4620	\ 'cprevious',
4621	\ 'crewind',
4622	\
4623	\ 'lNext',
4624	\ 'lNfile',
4625	\ 'labove',
4626	\ 'lbelow',
4627	\ 'lfirst',
4628	\ 'llast',
4629	\ 'lnewer',
4630	\ 'lnext',
4631	\ 'lnfile',
4632	\ 'lolder',
4633	\ 'lprevious',
4634	\ 'lrewind',
4635	\ ]
4636  for cmd in commands
4637    call assert_fails('-1' .. cmd, 'E16:')
4638    call assert_fails('.' .. cmd, 'E16:')
4639    call assert_fails('%' .. cmd, 'E16:')
4640    call assert_fails('$' .. cmd, 'E16:')
4641  endfor
4642endfunc
4643
4644" Test for aborting quickfix commands using QuickFixCmdPre
4645func Xtest_qfcmd_abort(cchar)
4646  call s:setup_commands(a:cchar)
4647
4648  call g:Xsetlist([], 'f')
4649
4650  " cexpr/lexpr
4651  let e = ''
4652  try
4653    Xexpr ["F1:10:Line10", "F2:20:Line20"]
4654  catch /.*/
4655    let e = v:exception
4656  endtry
4657  call assert_equal('AbortCmd', e)
4658  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4659
4660  " cfile/lfile
4661  call writefile(["F1:10:Line10", "F2:20:Line20"], 'Xfile1')
4662  let e = ''
4663  try
4664    Xfile Xfile1
4665  catch /.*/
4666    let e = v:exception
4667  endtry
4668  call assert_equal('AbortCmd', e)
4669  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4670  call delete('Xfile1')
4671
4672  " cgetbuffer/lgetbuffer
4673  enew!
4674  call append(0, ["F1:10:Line10", "F2:20:Line20"])
4675  let e = ''
4676  try
4677    Xgetbuffer
4678  catch /.*/
4679    let e = v:exception
4680  endtry
4681  call assert_equal('AbortCmd', e)
4682  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4683  enew!
4684
4685  " vimgrep/lvimgrep
4686  let e = ''
4687  try
4688    Xvimgrep /func/ test_quickfix.vim
4689  catch /.*/
4690    let e = v:exception
4691  endtry
4692  call assert_equal('AbortCmd', e)
4693  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4694
4695  " helpgrep/lhelpgrep
4696  let e = ''
4697  try
4698    Xhelpgrep quickfix
4699  catch /.*/
4700    let e = v:exception
4701  endtry
4702  call assert_equal('AbortCmd', e)
4703  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4704
4705  " grep/lgrep
4706  if has('unix')
4707    let e = ''
4708    try
4709      silent Xgrep func test_quickfix.vim
4710    catch /.*/
4711      let e = v:exception
4712    endtry
4713    call assert_equal('AbortCmd', e)
4714    call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4715  endif
4716endfunc
4717
4718func Test_qfcmd_abort()
4719  augroup QF_Test
4720    au!
4721    autocmd  QuickFixCmdPre * throw "AbortCmd"
4722  augroup END
4723
4724  call Xtest_qfcmd_abort('c')
4725  call Xtest_qfcmd_abort('l')
4726
4727  augroup QF_Test
4728    au!
4729  augroup END
4730endfunc
4731
4732" Test for using a file in one of the parent directories.
4733func Test_search_in_dirstack()
4734  call mkdir('Xtestdir/a/b/c', 'p')
4735  let save_cwd = getcwd()
4736  call writefile(["X1_L1", "X1_L2"], 'Xtestdir/Xfile1')
4737  call writefile(["X2_L1", "X2_L2"], 'Xtestdir/a/Xfile2')
4738  call writefile(["X3_L1", "X3_L2"], 'Xtestdir/a/b/Xfile3')
4739  call writefile(["X4_L1", "X4_L2"], 'Xtestdir/a/b/c/Xfile4')
4740
4741  let lines = "Entering dir Xtestdir\n" .
4742	      \ "Entering dir a\n" .
4743	      \ "Entering dir b\n" .
4744	      \ "Xfile2:2:X2_L2\n" .
4745	      \ "Leaving dir a\n" .
4746	      \ "Xfile1:2:X1_L2\n" .
4747	      \ "Xfile3:1:X3_L1\n" .
4748	      \ "Entering dir c\n" .
4749	      \ "Xfile4:2:X4_L2\n" .
4750	      \ "Leaving dir c\n"
4751  set efm=%DEntering\ dir\ %f,%XLeaving\ dir\ %f,%f:%l:%m
4752  cexpr lines .. "Leaving dir Xtestdir|\n" | let next = 1
4753  call assert_equal(11, getqflist({'size' : 0}).size)
4754  call assert_equal(4, getqflist({'idx' : 0}).idx)
4755  call assert_equal('X2_L2', getline('.'))
4756  call assert_equal(1, next)
4757  cnext
4758  call assert_equal(6, getqflist({'idx' : 0}).idx)
4759  call assert_equal('X1_L2', getline('.'))
4760  cnext
4761  call assert_equal(7, getqflist({'idx' : 0}).idx)
4762  call assert_equal(1, line('$'))
4763  call assert_equal('', getline(1))
4764  cnext
4765  call assert_equal(9, getqflist({'idx' : 0}).idx)
4766  call assert_equal(1, line('$'))
4767  call assert_equal('', getline(1))
4768
4769  set efm&
4770  exe 'cd ' . save_cwd
4771  call delete('Xtestdir', 'rf')
4772endfunc
4773
4774" Test for :cquit
4775func Test_cquit()
4776  " Exit Vim with a non-zero value
4777  if RunVim([], ["cquit 7"], '')
4778    call assert_equal(7, v:shell_error)
4779  endif
4780
4781  if RunVim([], ["50cquit"], '')
4782    call assert_equal(50, v:shell_error)
4783  endif
4784
4785  " Exit Vim with default value
4786  if RunVim([], ["cquit"], '')
4787    call assert_equal(1, v:shell_error)
4788  endif
4789
4790  " Exit Vim with zero value
4791  if RunVim([], ["cquit 0"], '')
4792    call assert_equal(0, v:shell_error)
4793  endif
4794
4795  " Exit Vim with negative value
4796  call assert_fails('-3cquit', 'E16:')
4797endfunc
4798
4799" Test for getting a specific item from a quickfix list
4800func Xtest_getqflist_by_idx(cchar)
4801  call s:setup_commands(a:cchar)
4802  " Empty list
4803  call assert_equal([], g:Xgetlist({'idx' : 1, 'items' : 0}).items)
4804  Xexpr ['F1:10:L10', 'F1:20:L20']
4805  let l = g:Xgetlist({'idx' : 2, 'items' : 0}).items
4806  call assert_equal(bufnr('F1'), l[0].bufnr)
4807  call assert_equal(20, l[0].lnum)
4808  call assert_equal('L20', l[0].text)
4809  call assert_equal([], g:Xgetlist({'idx' : -1, 'items' : 0}).items)
4810  call assert_equal([], g:Xgetlist({'idx' : 3, 'items' : 0}).items)
4811  %bwipe!
4812endfunc
4813
4814func Test_getqflist_by_idx()
4815  call Xtest_getqflist_by_idx('c')
4816  call Xtest_getqflist_by_idx('l')
4817endfunc
4818
4819" Test for the 'quickfixtextfunc' setting
4820func Tqfexpr(info)
4821  if a:info.quickfix
4822    let qfl = getqflist({'id' : a:info.id, 'idx' : a:info.idx,
4823          \ 'items' : 1}).items
4824  else
4825    let qfl = getloclist(0, {'id' : a:info.id, 'idx' : a:info.idx,
4826          \ 'items' : 1}).items
4827  endif
4828
4829  let e = qfl[0]
4830  let s = ''
4831  if e.bufnr != 0
4832    let bname = bufname(e.bufnr)
4833    let s ..= fnamemodify(bname, ':.')
4834  endif
4835  let s ..= '-'
4836  let s ..= 'L' .. string(e.lnum) .. 'C' .. string(e.col) .. '-'
4837  let s ..= e.text
4838
4839  return s
4840endfunc
4841
4842func Xtest_qftextfunc(cchar)
4843  call s:setup_commands(a:cchar)
4844
4845  set efm=%f:%l:%c:%m
4846  set quickfixtextfunc=Tqfexpr
4847  Xexpr ['F1:10:2:green', 'F1:20:4:blue']
4848  Xwindow
4849  call assert_equal('F1-L10C2-green', getline(1))
4850  call assert_equal('F1-L20C4-blue', getline(2))
4851  Xclose
4852  set quickfixtextfunc&vim
4853  Xwindow
4854  call assert_equal('F1|10 col 2| green', getline(1))
4855  call assert_equal('F1|20 col 4| blue', getline(2))
4856  Xclose
4857  set efm&
4858  set quickfixtextfunc&
4859
4860  " Test for per list 'quickfixtextfunc' setting
4861  func PerQfText(info)
4862    if a:info.quickfix
4863      let qfl = getqflist({'id' : a:info.id, 'idx' : a:info.idx,
4864            \ 'items' : 1}).items
4865    else
4866      let qfl = getloclist(0, {'id' : a:info.id, 'idx' : a:info.idx,
4867            \ 'items' : 1}).items
4868    endif
4869    if empty(qfl)
4870      return ''
4871    endif
4872    return 'Line ' .. qfl[0].lnum .. ', Col ' .. qfl[0].col
4873  endfunc
4874  set quickfixtextfunc=Tqfexpr
4875  call g:Xsetlist([], ' ', {'quickfixtextfunc' : "PerQfText"})
4876  Xaddexpr ['F1:10:2:green', 'F1:20:4:blue']
4877  Xwindow
4878  call assert_equal('Line 10, Col 2', getline(1))
4879  call assert_equal('Line 20, Col 4', getline(2))
4880  Xclose
4881  call g:Xsetlist([], 'r', {'quickfixtextfunc' : ''})
4882  set quickfixtextfunc&
4883  delfunc PerQfText
4884
4885  " Non-existing function
4886  set quickfixtextfunc=Tabc
4887  call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue']", 'E117:')
4888  call assert_fails("Xwindow", 'E117:')
4889  Xclose
4890  set quickfixtextfunc&
4891
4892  " set option to a non-function
4893  set quickfixtextfunc=[10,\ 20]
4894  call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue']", 'E117:')
4895  call assert_fails("Xwindow", 'E117:')
4896  Xclose
4897  set quickfixtextfunc&
4898
4899  " set option to a function with different set of arguments
4900  func Xqftext(a, b, c)
4901    return a:a .. a:b .. a:c
4902  endfunc
4903  set quickfixtextfunc=Xqftext
4904  call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue']", 'E119:')
4905  call assert_fails("Xwindow", 'E119:')
4906  Xclose
4907  set quickfixtextfunc&
4908  delfunc Xqftext
4909endfunc
4910
4911func Test_qftextfunc()
4912  call Xtest_qftextfunc('c')
4913  call Xtest_qftextfunc('l')
4914endfunc
4915
4916" vim: shiftwidth=2 sts=2 expandtab
4917