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