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