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