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