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  " Adding a non-valid entry should not mark the list as having valid entries
1303  call g:Xsetlist([{'bufnr':a:bnum, 'lnum':5, 'valid':0}], 'a')
1304  Xwindow
1305  call assert_equal(1, winnr('$'))
1306
1307  " :cnext/:cprev should still work even with invalid entries in the list
1308  let l = [{'bufnr' : a:bnum, 'lnum' : 1, 'text' : '1', 'valid' : 0},
1309	      \ {'bufnr' : a:bnum, 'lnum' : 2, 'text' : '2', 'valid' : 0}]
1310  call g:Xsetlist(l)
1311  Xnext
1312  call assert_equal(2, g:Xgetlist({'idx' : 0}).idx)
1313  Xprev
1314  call assert_equal(1, g:Xgetlist({'idx' : 0}).idx)
1315  " :cnext/:cprev should still work after appending invalid entries to an
1316  " empty list
1317  call g:Xsetlist([])
1318  call g:Xsetlist(l, 'a')
1319  Xnext
1320  call assert_equal(2, g:Xgetlist({'idx' : 0}).idx)
1321  Xprev
1322  call assert_equal(1, g:Xgetlist({'idx' : 0}).idx)
1323
1324  call g:Xsetlist([{'text':'Text1', 'valid':1}])
1325  Xwindow
1326  call assert_equal(2, winnr('$'))
1327  Xclose
1328  let save_efm = &efm
1329  set efm=%m
1330  Xgetexpr 'TestMessage'
1331  let l = g:Xgetlist()
1332  call g:Xsetlist(l)
1333  call assert_equal(1, g:Xgetlist()[0].valid)
1334  let &efm = save_efm
1335
1336  " Error cases:
1337  " Refer to a non-existing buffer and pass a non-dictionary type
1338  call assert_fails("call g:Xsetlist([{'bufnr':998, 'lnum':4}," .
1339	      \ " {'bufnr':999, 'lnum':5}])", 'E92:')
1340  call g:Xsetlist([[1, 2,3]])
1341  call assert_equal(0, len(g:Xgetlist()))
1342endfunc
1343
1344func Test_setqflist()
1345  new Xtestfile | only
1346  let bnum = bufnr('%')
1347  call setline(1, range(1,5))
1348
1349  call SetXlistTests('c', bnum)
1350  call SetXlistTests('l', bnum)
1351
1352  enew!
1353  call delete('Xtestfile')
1354endfunc
1355
1356func Xlist_empty_middle(cchar)
1357  call s:setup_commands(a:cchar)
1358
1359  " create three quickfix lists
1360  let @/ = 'Test_'
1361  Xvimgrep // test_quickfix.vim
1362  let testlen = len(g:Xgetlist())
1363  call assert_true(testlen > 0)
1364  Xvimgrep empty test_quickfix.vim
1365  call assert_true(len(g:Xgetlist()) > 0)
1366  Xvimgrep matches test_quickfix.vim
1367  let matchlen = len(g:Xgetlist())
1368  call assert_true(matchlen > 0)
1369  Xolder
1370  " make the middle list empty
1371  call g:Xsetlist([], 'r')
1372  call assert_true(len(g:Xgetlist()) == 0)
1373  Xolder
1374  call assert_equal(testlen, len(g:Xgetlist()))
1375  Xnewer
1376  Xnewer
1377  call assert_equal(matchlen, len(g:Xgetlist()))
1378endfunc
1379
1380func Test_setqflist_empty_middle()
1381  call Xlist_empty_middle('c')
1382  call Xlist_empty_middle('l')
1383endfunc
1384
1385func Xlist_empty_older(cchar)
1386  call s:setup_commands(a:cchar)
1387
1388  " create three quickfix lists
1389  Xvimgrep one test_quickfix.vim
1390  let onelen = len(g:Xgetlist())
1391  call assert_true(onelen > 0)
1392  Xvimgrep two test_quickfix.vim
1393  let twolen = len(g:Xgetlist())
1394  call assert_true(twolen > 0)
1395  Xvimgrep three test_quickfix.vim
1396  let threelen = len(g:Xgetlist())
1397  call assert_true(threelen > 0)
1398  Xolder 2
1399  " make the first list empty, check the others didn't change
1400  call g:Xsetlist([], 'r')
1401  call assert_true(len(g:Xgetlist()) == 0)
1402  Xnewer
1403  call assert_equal(twolen, len(g:Xgetlist()))
1404  Xnewer
1405  call assert_equal(threelen, len(g:Xgetlist()))
1406endfunc
1407
1408func Test_setqflist_empty_older()
1409  call Xlist_empty_older('c')
1410  call Xlist_empty_older('l')
1411endfunc
1412
1413func XquickfixSetListWithAct(cchar)
1414  call s:setup_commands(a:cchar)
1415
1416  let list1 = [{'filename': 'fnameA', 'text': 'A'},
1417          \    {'filename': 'fnameB', 'text': 'B'}]
1418  let list2 = [{'filename': 'fnameC', 'text': 'C'},
1419          \    {'filename': 'fnameD', 'text': 'D'},
1420          \    {'filename': 'fnameE', 'text': 'E'}]
1421
1422  " {action} is unspecified.  Same as specifing ' '.
1423  new | only
1424  silent! Xnewer 99
1425  call g:Xsetlist(list1)
1426  call g:Xsetlist(list2)
1427  let li = g:Xgetlist()
1428  call assert_equal(3, len(li))
1429  call assert_equal('C', li[0]['text'])
1430  call assert_equal('D', li[1]['text'])
1431  call assert_equal('E', li[2]['text'])
1432  silent! Xolder
1433  let li = g:Xgetlist()
1434  call assert_equal(2, len(li))
1435  call assert_equal('A', li[0]['text'])
1436  call assert_equal('B', li[1]['text'])
1437
1438  " {action} is specified ' '.
1439  new | only
1440  silent! Xnewer 99
1441  call g:Xsetlist(list1)
1442  call g:Xsetlist(list2, ' ')
1443  let li = g:Xgetlist()
1444  call assert_equal(3, len(li))
1445  call assert_equal('C', li[0]['text'])
1446  call assert_equal('D', li[1]['text'])
1447  call assert_equal('E', li[2]['text'])
1448  silent! Xolder
1449  let li = g:Xgetlist()
1450  call assert_equal(2, len(li))
1451  call assert_equal('A', li[0]['text'])
1452  call assert_equal('B', li[1]['text'])
1453
1454  " {action} is specified 'a'.
1455  new | only
1456  silent! Xnewer 99
1457  call g:Xsetlist(list1)
1458  call g:Xsetlist(list2, 'a')
1459  let li = g:Xgetlist()
1460  call assert_equal(5, len(li))
1461  call assert_equal('A', li[0]['text'])
1462  call assert_equal('B', li[1]['text'])
1463  call assert_equal('C', li[2]['text'])
1464  call assert_equal('D', li[3]['text'])
1465  call assert_equal('E', li[4]['text'])
1466
1467  " {action} is specified 'r'.
1468  new | only
1469  silent! Xnewer 99
1470  call g:Xsetlist(list1)
1471  call g:Xsetlist(list2, 'r')
1472  let li = g:Xgetlist()
1473  call assert_equal(3, len(li))
1474  call assert_equal('C', li[0]['text'])
1475  call assert_equal('D', li[1]['text'])
1476  call assert_equal('E', li[2]['text'])
1477
1478  " Test for wrong value.
1479  new | only
1480  call assert_fails("call g:Xsetlist(0)", 'E714:')
1481  call assert_fails("call g:Xsetlist(list1, '')", 'E927:')
1482  call assert_fails("call g:Xsetlist(list1, 'aa')", 'E927:')
1483  call assert_fails("call g:Xsetlist(list1, ' a')", 'E927:')
1484  call assert_fails("call g:Xsetlist(list1, 0)", 'E928:')
1485endfunc
1486
1487func Test_setqflist_invalid_nr()
1488  " The following command used to crash Vim
1489  call setqflist([], ' ', {'nr' : $XXX_DOES_NOT_EXIST})
1490endfunc
1491
1492func Test_quickfix_set_list_with_act()
1493  call XquickfixSetListWithAct('c')
1494  call XquickfixSetListWithAct('l')
1495endfunc
1496
1497func XLongLinesTests(cchar)
1498  let l = g:Xgetlist()
1499
1500  call assert_equal(4, len(l))
1501  call assert_equal(1, l[0].lnum)
1502  call assert_equal(1, l[0].col)
1503  call assert_equal(1975, len(l[0].text))
1504  call assert_equal(2, l[1].lnum)
1505  call assert_equal(1, l[1].col)
1506  call assert_equal(4070, len(l[1].text))
1507  call assert_equal(3, l[2].lnum)
1508  call assert_equal(1, l[2].col)
1509  call assert_equal(4070, len(l[2].text))
1510  call assert_equal(4, l[3].lnum)
1511  call assert_equal(1, l[3].col)
1512  call assert_equal(10, len(l[3].text))
1513
1514  call g:Xsetlist([], 'r')
1515endfunc
1516
1517func s:long_lines_tests(cchar)
1518  call s:setup_commands(a:cchar)
1519
1520  let testfile = 'samples/quickfix.txt'
1521
1522  " file
1523  exe 'Xgetfile' testfile
1524  call XLongLinesTests(a:cchar)
1525
1526  " list
1527  Xexpr readfile(testfile)
1528  call XLongLinesTests(a:cchar)
1529
1530  " string
1531  Xexpr join(readfile(testfile), "\n")
1532  call XLongLinesTests(a:cchar)
1533
1534  " buffer
1535  exe 'edit' testfile
1536  exe 'Xbuffer' bufnr('%')
1537  call XLongLinesTests(a:cchar)
1538endfunc
1539
1540func Test_long_lines()
1541  call s:long_lines_tests('c')
1542  call s:long_lines_tests('l')
1543endfunc
1544
1545func s:create_test_file(filename)
1546  let l = []
1547  for i in range(1, 20)
1548      call add(l, 'Line' . i)
1549  endfor
1550  call writefile(l, a:filename)
1551endfunc
1552
1553func Test_switchbuf()
1554  call s:create_test_file('Xqftestfile1')
1555  call s:create_test_file('Xqftestfile2')
1556  call s:create_test_file('Xqftestfile3')
1557
1558  new | only
1559  edit Xqftestfile1
1560  let file1_winid = win_getid()
1561  new Xqftestfile2
1562  let file2_winid = win_getid()
1563  cgetexpr ['Xqftestfile1:5:Line5',
1564		\ 'Xqftestfile1:6:Line6',
1565		\ 'Xqftestfile2:10:Line10',
1566		\ 'Xqftestfile2:11:Line11',
1567		\ 'Xqftestfile3:15:Line15',
1568		\ 'Xqftestfile3:16:Line16']
1569
1570  new
1571  let winid = win_getid()
1572  cfirst | cnext
1573  call assert_equal(winid, win_getid())
1574  2cnext
1575  call assert_equal(winid, win_getid())
1576  2cnext
1577  call assert_equal(winid, win_getid())
1578  enew
1579
1580  set switchbuf=useopen
1581  cfirst | cnext
1582  call assert_equal(file1_winid, win_getid())
1583  2cnext
1584  call assert_equal(file2_winid, win_getid())
1585  2cnext
1586  call assert_equal(file2_winid, win_getid())
1587
1588  enew | only
1589  set switchbuf=usetab
1590  tabedit Xqftestfile1
1591  tabedit Xqftestfile2
1592  tabedit Xqftestfile3
1593  tabfirst
1594  cfirst | cnext
1595  call assert_equal(2, tabpagenr())
1596  2cnext
1597  call assert_equal(3, tabpagenr())
1598  6cnext
1599  call assert_equal(4, tabpagenr())
1600  2cpfile
1601  call assert_equal(2, tabpagenr())
1602  2cnfile
1603  call assert_equal(4, tabpagenr())
1604  tabfirst | tabonly | enew
1605
1606  set switchbuf=split
1607  cfirst | cnext
1608  call assert_equal(1, winnr('$'))
1609  cnext | cnext
1610  call assert_equal(2, winnr('$'))
1611  cnext | cnext
1612  call assert_equal(3, winnr('$'))
1613  enew | only
1614
1615  set switchbuf=newtab
1616  cfirst | cnext
1617  call assert_equal(1, tabpagenr('$'))
1618  cnext | cnext
1619  call assert_equal(2, tabpagenr('$'))
1620  cnext | cnext
1621  call assert_equal(3, tabpagenr('$'))
1622  tabfirst | enew | tabonly | only
1623
1624  set switchbuf=
1625  edit Xqftestfile1
1626  let file1_winid = win_getid()
1627  new Xqftestfile2
1628  let file2_winid = win_getid()
1629  copen
1630  exe "normal 1G\<CR>"
1631  call assert_equal(file1_winid, win_getid())
1632  copen
1633  exe "normal 3G\<CR>"
1634  call assert_equal(file2_winid, win_getid())
1635  copen | only
1636  exe "normal 5G\<CR>"
1637  call assert_equal(2, winnr('$'))
1638  call assert_equal(1, bufwinnr('Xqftestfile3'))
1639
1640  " If only quickfix window is open in the current tabpage, jumping to an
1641  " entry with 'switchubf' set to 'usetab' should search in other tabpages.
1642  enew | only
1643  set switchbuf=usetab
1644  tabedit Xqftestfile1
1645  tabedit Xqftestfile2
1646  tabedit Xqftestfile3
1647  tabfirst
1648  copen | only
1649  clast
1650  call assert_equal(4, tabpagenr())
1651  tabfirst | tabonly | enew | only
1652
1653  call delete('Xqftestfile1')
1654  call delete('Xqftestfile2')
1655  call delete('Xqftestfile3')
1656  set switchbuf&vim
1657
1658  enew | only
1659endfunc
1660
1661func Xadjust_qflnum(cchar)
1662  call s:setup_commands(a:cchar)
1663
1664  enew | only
1665
1666  let fname = 'Xqftestfile' . a:cchar
1667  call s:create_test_file(fname)
1668  exe 'edit ' . fname
1669
1670  Xgetexpr [fname . ':5:Line5',
1671	      \ fname . ':10:Line10',
1672	      \ fname . ':15:Line15',
1673	      \ fname . ':20:Line20']
1674
1675  6,14delete
1676  call append(6, ['Buffer', 'Window'])
1677
1678  let l = g:Xgetlist()
1679
1680  call assert_equal(5, l[0].lnum)
1681  call assert_equal(6, l[2].lnum)
1682  call assert_equal(13, l[3].lnum)
1683
1684  enew!
1685  call delete(fname)
1686endfunc
1687
1688func Test_adjust_lnum()
1689  call setloclist(0, [])
1690  call Xadjust_qflnum('c')
1691  call setqflist([])
1692  call Xadjust_qflnum('l')
1693endfunc
1694
1695" Tests for the :grep/:lgrep and :grepadd/:lgrepadd commands
1696func s:test_xgrep(cchar)
1697  call s:setup_commands(a:cchar)
1698
1699  " The following lines are used for the grep test. Don't remove.
1700  " Grep_Test_Text: Match 1
1701  " Grep_Test_Text: Match 2
1702  " GrepAdd_Test_Text: Match 1
1703  " GrepAdd_Test_Text: Match 2
1704  enew! | only
1705  set makeef&vim
1706  silent Xgrep Grep_Test_Text: test_quickfix.vim
1707  call assert_true(len(g:Xgetlist()) == 3)
1708  Xopen
1709  call assert_true(w:quickfix_title =~ '^:grep')
1710  Xclose
1711  enew
1712  set makeef=Temp_File_##
1713  silent Xgrepadd GrepAdd_Test_Text: test_quickfix.vim
1714  call assert_true(len(g:Xgetlist()) == 6)
1715endfunc
1716
1717func Test_grep()
1718  if !has('unix')
1719    " The grepprg may not be set on non-Unix systems
1720    return
1721  endif
1722
1723  call s:test_xgrep('c')
1724  call s:test_xgrep('l')
1725endfunc
1726
1727func Test_two_windows()
1728  " Use one 'errorformat' for two windows.  Add an expression to each of them,
1729  " make sure they each keep their own state.
1730  set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f'
1731  call mkdir('Xone/a', 'p')
1732  call mkdir('Xtwo/a', 'p')
1733  let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7']
1734  call writefile(lines, 'Xone/a/one.txt')
1735  call writefile(lines, 'Xtwo/a/two.txt')
1736
1737  new one
1738  let one_id = win_getid()
1739  lexpr ""
1740  new two
1741  let two_id = win_getid()
1742  lexpr ""
1743
1744  laddexpr "Entering dir 'Xtwo/a'"
1745  call win_gotoid(one_id)
1746  laddexpr "Entering dir 'Xone/a'"
1747  call win_gotoid(two_id)
1748  laddexpr 'two.txt:5:two two two'
1749  call win_gotoid(one_id)
1750  laddexpr 'one.txt:3:one one one'
1751
1752  let loc_one = getloclist(one_id)
1753  call assert_equal('Xone/a/one.txt', bufname(loc_one[1].bufnr))
1754  call assert_equal(3, loc_one[1].lnum)
1755
1756  let loc_two = getloclist(two_id)
1757  call assert_equal('Xtwo/a/two.txt', bufname(loc_two[1].bufnr))
1758  call assert_equal(5, loc_two[1].lnum)
1759
1760  call win_gotoid(one_id)
1761  bwipe!
1762  call win_gotoid(two_id)
1763  bwipe!
1764  call delete('Xone', 'rf')
1765  call delete('Xtwo', 'rf')
1766endfunc
1767
1768func XbottomTests(cchar)
1769  call s:setup_commands(a:cchar)
1770
1771  " Calling lbottom without any errors should fail
1772  if a:cchar == 'l'
1773      call assert_fails('lbottom', 'E776:')
1774  endif
1775
1776  call g:Xsetlist([{'filename': 'foo', 'lnum': 42}])
1777  Xopen
1778  let wid = win_getid()
1779  call assert_equal(1, line('.'))
1780  wincmd w
1781  call g:Xsetlist([{'filename': 'var', 'lnum': 24}], 'a')
1782  Xbottom
1783  call win_gotoid(wid)
1784  call assert_equal(2, line('.'))
1785  Xclose
1786endfunc
1787
1788" Tests for the :cbottom and :lbottom commands
1789func Test_cbottom()
1790  call XbottomTests('c')
1791  call XbottomTests('l')
1792endfunc
1793
1794func HistoryTest(cchar)
1795  call s:setup_commands(a:cchar)
1796
1797  " clear all lists after the first one, then replace the first one.
1798  call g:Xsetlist([])
1799  call assert_fails('Xolder 99', 'E380:')
1800  let entry = {'filename': 'foo', 'lnum': 42}
1801  call g:Xsetlist([entry], 'r')
1802  call g:Xsetlist([entry, entry])
1803  call g:Xsetlist([entry, entry, entry])
1804  let res = split(execute(a:cchar . 'hist'), "\n")
1805  call assert_equal(3, len(res))
1806  let common = 'errors     :set' . (a:cchar == 'c' ? 'qf' : 'loc') . 'list()'
1807  call assert_equal('  error list 1 of 3; 1 ' . common, res[0])
1808  call assert_equal('  error list 2 of 3; 2 ' . common, res[1])
1809  call assert_equal('> error list 3 of 3; 3 ' . common, res[2])
1810
1811  call g:Xsetlist([], 'f')
1812  let l = split(execute(a:cchar . 'hist'), "\n")
1813  call assert_equal('No entries', l[0])
1814
1815  " An empty list should still show the stack history
1816  call g:Xsetlist([])
1817  let res = split(execute(a:cchar . 'hist'), "\n")
1818  call assert_equal('> error list 1 of 1; 0 ' . common, res[0])
1819
1820  call g:Xsetlist([], 'f')
1821endfunc
1822
1823func Test_history()
1824  call HistoryTest('c')
1825  call HistoryTest('l')
1826endfunc
1827
1828func Test_duplicate_buf()
1829  " make sure we can get the highest buffer number
1830  edit DoesNotExist
1831  edit DoesNotExist2
1832  let last_buffer = bufnr("$")
1833
1834  " make sure only one buffer is created
1835  call writefile(['this one', 'that one'], 'Xgrepthis')
1836  vimgrep one Xgrepthis
1837  vimgrep one Xgrepthis
1838  call assert_equal(last_buffer + 1, bufnr("$"))
1839
1840  call delete('Xgrepthis')
1841endfunc
1842
1843" Quickfix/Location list set/get properties tests
1844func Xproperty_tests(cchar)
1845    call s:setup_commands(a:cchar)
1846
1847    " Error cases
1848    call assert_fails('call g:Xgetlist(99)', 'E715:')
1849    call assert_fails('call g:Xsetlist(99)', 'E714:')
1850    call assert_fails('call g:Xsetlist([], "a", [])', 'E715:')
1851
1852    " Set and get the title
1853    call g:Xsetlist([])
1854    Xopen
1855    wincmd p
1856    call g:Xsetlist([{'filename':'foo', 'lnum':27}])
1857    let s = g:Xsetlist([], 'a', {'title' : 'Sample'})
1858    call assert_equal(0, s)
1859    let d = g:Xgetlist({"title":1})
1860    call assert_equal('Sample', d.title)
1861    " Try setting title to a non-string value
1862    call assert_equal(-1, g:Xsetlist([], 'a', {'title' : ['Test']}))
1863    call assert_equal('Sample', g:Xgetlist({"title":1}).title)
1864
1865    Xopen
1866    call assert_equal('Sample', w:quickfix_title)
1867    Xclose
1868
1869    " Tests for action argument
1870    silent! Xolder 999
1871    let qfnr = g:Xgetlist({'all':1}).nr
1872    call g:Xsetlist([], 'r', {'title' : 'N1'})
1873    call assert_equal('N1', g:Xgetlist({'all':1}).title)
1874    call g:Xsetlist([], ' ', {'title' : 'N2'})
1875    call assert_equal(qfnr + 1, g:Xgetlist({'all':1}).nr)
1876
1877    let res = g:Xgetlist({'nr': 0})
1878    call assert_equal(qfnr + 1, res.nr)
1879    call assert_equal(['nr'], keys(res))
1880
1881    call g:Xsetlist([], ' ', {'title' : 'N3'})
1882    call assert_equal('N2', g:Xgetlist({'nr':2, 'title':1}).title)
1883
1884    " Changing the title of an earlier quickfix list
1885    call g:Xsetlist([], 'r', {'title' : 'NewTitle', 'nr' : 2})
1886    call assert_equal('NewTitle', g:Xgetlist({'nr':2, 'title':1}).title)
1887
1888    " Changing the title of an invalid quickfix list
1889    call assert_equal(-1, g:Xsetlist([], ' ',
1890		\ {'title' : 'SomeTitle', 'nr' : 99}))
1891    call assert_equal(-1, g:Xsetlist([], ' ',
1892		\ {'title' : 'SomeTitle', 'nr' : 'abc'}))
1893
1894    if a:cchar == 'c'
1895	copen
1896	call assert_equal({'winid':win_getid()}, getqflist({'winid':1}))
1897	cclose
1898    endif
1899
1900    " Invalid arguments
1901    call assert_fails('call g:Xgetlist([])', 'E715')
1902    call assert_fails('call g:Xsetlist([], "a", [])', 'E715')
1903    let s = g:Xsetlist([], 'a', {'abc':1})
1904    call assert_equal(-1, s)
1905
1906    call assert_equal({}, g:Xgetlist({'abc':1}))
1907    call assert_equal('', g:Xgetlist({'nr':99, 'title':1}).title)
1908    call assert_equal('', g:Xgetlist({'nr':[], 'title':1}).title)
1909
1910    if a:cchar == 'l'
1911	call assert_equal({}, getloclist(99, {'title': 1}))
1912    endif
1913
1914    " Context related tests
1915    let s = g:Xsetlist([], 'a', {'context':[1,2,3]})
1916    call assert_equal(0, s)
1917    call test_garbagecollect_now()
1918    let d = g:Xgetlist({'context':1})
1919    call assert_equal([1,2,3], d.context)
1920    call g:Xsetlist([], 'a', {'context':{'color':'green'}})
1921    let d = g:Xgetlist({'context':1})
1922    call assert_equal({'color':'green'}, d.context)
1923    call g:Xsetlist([], 'a', {'context':"Context info"})
1924    let d = g:Xgetlist({'context':1})
1925    call assert_equal("Context info", d.context)
1926    call g:Xsetlist([], 'a', {'context':246})
1927    let d = g:Xgetlist({'context':1})
1928    call assert_equal(246, d.context)
1929    if a:cchar == 'l'
1930	" Test for copying context across two different location lists
1931	new | only
1932	let w1_id = win_getid()
1933	let l = [1]
1934	call setloclist(0, [], 'a', {'context':l})
1935	new
1936	let w2_id = win_getid()
1937	call add(l, 2)
1938	call assert_equal([1, 2], getloclist(w1_id, {'context':1}).context)
1939	call assert_equal([1, 2], getloclist(w2_id, {'context':1}).context)
1940	unlet! l
1941	call assert_equal([1, 2], getloclist(w2_id, {'context':1}).context)
1942	only
1943	call setloclist(0, [], 'f')
1944	call assert_equal('', getloclist(0, {'context':1}).context)
1945    endif
1946
1947    " Test for changing the context of previous quickfix lists
1948    call g:Xsetlist([], 'f')
1949    Xexpr "One"
1950    Xexpr "Two"
1951    Xexpr "Three"
1952    call g:Xsetlist([], 'r', {'context' : [1], 'nr' : 1})
1953    call g:Xsetlist([], 'a', {'context' : [2], 'nr' : 2})
1954    " Also, check for setting the context using quickfix list number zero.
1955    call g:Xsetlist([], 'r', {'context' : [3], 'nr' : 0})
1956    call test_garbagecollect_now()
1957    let l = g:Xgetlist({'nr' : 1, 'context' : 1})
1958    call assert_equal([1], l.context)
1959    let l = g:Xgetlist({'nr' : 2, 'context' : 1})
1960    call assert_equal([2], l.context)
1961    let l = g:Xgetlist({'nr' : 3, 'context' : 1})
1962    call assert_equal([3], l.context)
1963
1964    " Test for changing the context through reference and for garbage
1965    " collection of quickfix context
1966    let l = ["red"]
1967    call g:Xsetlist([], ' ', {'context' : l})
1968    call add(l, "blue")
1969    let x = g:Xgetlist({'context' : 1})
1970    call add(x.context, "green")
1971    call assert_equal(["red", "blue", "green"], l)
1972    call assert_equal(["red", "blue", "green"], x.context)
1973    unlet l
1974    call test_garbagecollect_now()
1975    let m = g:Xgetlist({'context' : 1})
1976    call assert_equal(["red", "blue", "green"], m.context)
1977
1978    " Test for setting/getting items
1979    Xexpr ""
1980    let qfprev = g:Xgetlist({'nr':0})
1981    let s = g:Xsetlist([], ' ', {'title':'Green',
1982		\ 'items' : [{'filename':'F1', 'lnum':10}]})
1983    call assert_equal(0, s)
1984    let qfcur = g:Xgetlist({'nr':0})
1985    call assert_true(qfcur.nr == qfprev.nr + 1)
1986    let l = g:Xgetlist({'items':1})
1987    call assert_equal('F1', bufname(l.items[0].bufnr))
1988    call assert_equal(10, l.items[0].lnum)
1989    call g:Xsetlist([], 'a', {'items' : [{'filename':'F2', 'lnum':20},
1990		\  {'filename':'F2', 'lnum':30}]})
1991    let l = g:Xgetlist({'items':1})
1992    call assert_equal('F2', bufname(l.items[2].bufnr))
1993    call assert_equal(30, l.items[2].lnum)
1994    call g:Xsetlist([], 'r', {'items' : [{'filename':'F3', 'lnum':40}]})
1995    let l = g:Xgetlist({'items':1})
1996    call assert_equal('F3', bufname(l.items[0].bufnr))
1997    call assert_equal(40, l.items[0].lnum)
1998    call g:Xsetlist([], 'r', {'items' : []})
1999    let l = g:Xgetlist({'items':1})
2000    call assert_equal(0, len(l.items))
2001
2002    call g:Xsetlist([], 'r', {'title' : 'TestTitle'})
2003    call g:Xsetlist([], 'r', {'items' : [{'filename' : 'F1', 'lnum' : 10, 'text' : 'L10'}]})
2004    call g:Xsetlist([], 'r', {'items' : [{'filename' : 'F1', 'lnum' : 10, 'text' : 'L10'}]})
2005    call assert_equal('TestTitle', g:Xgetlist({'title' : 1}).title)
2006
2007    " Test for getting id of window associated with a location list window
2008    if a:cchar == 'l'
2009      only
2010      call assert_equal(0, g:Xgetlist({'all' : 1}).filewinid)
2011      let wid = win_getid()
2012      Xopen
2013      call assert_equal(wid, g:Xgetlist({'filewinid' : 1}).filewinid)
2014      wincmd w
2015      call assert_equal(0, g:Xgetlist({'filewinid' : 1}).filewinid)
2016      only
2017    endif
2018
2019    " The following used to crash Vim with address sanitizer
2020    call g:Xsetlist([], 'f')
2021    call g:Xsetlist([], 'a', {'items' : [{'filename':'F1', 'lnum':10}]})
2022    call assert_equal(10, g:Xgetlist({'items':1}).items[0].lnum)
2023
2024    " Try setting the items using a string
2025    call assert_equal(-1, g:Xsetlist([], ' ', {'items' : 'Test'}))
2026
2027    " Save and restore the quickfix stack
2028    call g:Xsetlist([], 'f')
2029    call assert_equal(0, g:Xgetlist({'nr':'$'}).nr)
2030    Xexpr "File1:10:Line1"
2031    Xexpr "File2:20:Line2"
2032    Xexpr "File3:30:Line3"
2033    let last_qf = g:Xgetlist({'nr':'$'}).nr
2034    call assert_equal(3, last_qf)
2035    let qstack = []
2036    for i in range(1, last_qf)
2037	let qstack = add(qstack, g:Xgetlist({'nr':i, 'all':1}))
2038    endfor
2039    call g:Xsetlist([], 'f')
2040    for i in range(len(qstack))
2041	call g:Xsetlist([], ' ', qstack[i])
2042    endfor
2043    call assert_equal(3, g:Xgetlist({'nr':'$'}).nr)
2044    call assert_equal(10, g:Xgetlist({'nr':1, 'items':1}).items[0].lnum)
2045    call assert_equal(20, g:Xgetlist({'nr':2, 'items':1}).items[0].lnum)
2046    call assert_equal(30, g:Xgetlist({'nr':3, 'items':1}).items[0].lnum)
2047    call g:Xsetlist([], 'f')
2048
2049    " Swap two quickfix lists
2050    Xexpr "File1:10:Line10"
2051    Xexpr "File2:20:Line20"
2052    Xexpr "File3:30:Line30"
2053    call g:Xsetlist([], 'r', {'nr':1,'title':'Colors','context':['Colors']})
2054    call g:Xsetlist([], 'r', {'nr':2,'title':'Fruits','context':['Fruits']})
2055    let l1=g:Xgetlist({'nr':1,'all':1})
2056    let l2=g:Xgetlist({'nr':2,'all':1})
2057    let save_id = l1.id
2058    let l1.id=l2.id
2059    let l2.id=save_id
2060    call g:Xsetlist([], 'r', l1)
2061    call g:Xsetlist([], 'r', l2)
2062    let newl1=g:Xgetlist({'nr':1,'all':1})
2063    let newl2=g:Xgetlist({'nr':2,'all':1})
2064    call assert_equal('Fruits', newl1.title)
2065    call assert_equal(['Fruits'], newl1.context)
2066    call assert_equal('Line20', newl1.items[0].text)
2067    call assert_equal('Colors', newl2.title)
2068    call assert_equal(['Colors'], newl2.context)
2069    call assert_equal('Line10', newl2.items[0].text)
2070    call g:Xsetlist([], 'f')
2071endfunc
2072
2073func Test_qf_property()
2074    call Xproperty_tests('c')
2075    call Xproperty_tests('l')
2076endfunc
2077
2078" Test for setting the current index in the location/quickfix list
2079func Xtest_setqfidx(cchar)
2080  call s:setup_commands(a:cchar)
2081
2082  Xgetexpr "F1:10:1:Line1\nF2:20:2:Line2\nF3:30:3:Line3"
2083  Xgetexpr "F4:10:1:Line1\nF5:20:2:Line2\nF6:30:3:Line3"
2084  Xgetexpr "F7:10:1:Line1\nF8:20:2:Line2\nF9:30:3:Line3"
2085
2086  call g:Xsetlist([], 'a', {'nr' : 3, 'idx' : 2})
2087  call g:Xsetlist([], 'a', {'nr' : 2, 'idx' : 2})
2088  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 3})
2089  Xolder 2
2090  Xopen
2091  call assert_equal(3, line('.'))
2092  Xnewer
2093  call assert_equal(2, line('.'))
2094  Xnewer
2095  call assert_equal(2, line('.'))
2096  " Update the current index with the quickfix window open
2097  wincmd w
2098  call g:Xsetlist([], 'a', {'nr' : 3, 'idx' : 3})
2099  Xopen
2100  call assert_equal(3, line('.'))
2101  Xclose
2102
2103  " Set the current index to the last entry
2104  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : '$'})
2105  call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx)
2106  " A large value should set the index to the last index
2107  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 1})
2108  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 999})
2109  call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx)
2110  " Invalid index values
2111  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : -1})
2112  call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx)
2113  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 0})
2114  call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx)
2115  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 'xx'})
2116  call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx)
2117  call assert_fails("call g:Xsetlist([], 'a', {'nr':1, 'idx':[]})", 'E745:')
2118
2119  call g:Xsetlist([], 'f')
2120  new | only
2121endfunc
2122
2123func Test_setqfidx()
2124  call Xtest_setqfidx('c')
2125  call Xtest_setqfidx('l')
2126endfunc
2127
2128" Tests for the QuickFixCmdPre/QuickFixCmdPost autocommands
2129func QfAutoCmdHandler(loc, cmd)
2130  call add(g:acmds, a:loc . a:cmd)
2131endfunc
2132
2133func Test_Autocmd()
2134  autocmd QuickFixCmdPre * call QfAutoCmdHandler('pre', expand('<amatch>'))
2135  autocmd QuickFixCmdPost * call QfAutoCmdHandler('post', expand('<amatch>'))
2136
2137  let g:acmds = []
2138  cexpr "F1:10:Line 10"
2139  caddexpr "F1:20:Line 20"
2140  cgetexpr "F1:30:Line 30"
2141  cexpr ""
2142  caddexpr ""
2143  cgetexpr ""
2144  silent! cexpr non_existing_func()
2145  silent! caddexpr non_existing_func()
2146  silent! cgetexpr non_existing_func()
2147  let l = ['precexpr',
2148	      \ 'postcexpr',
2149	      \ 'precaddexpr',
2150	      \ 'postcaddexpr',
2151	      \ 'precgetexpr',
2152	      \ 'postcgetexpr',
2153	      \ 'precexpr',
2154	      \ 'postcexpr',
2155	      \ 'precaddexpr',
2156	      \ 'postcaddexpr',
2157	      \ 'precgetexpr',
2158	      \ 'postcgetexpr',
2159	      \ 'precexpr',
2160	      \ 'precaddexpr',
2161	      \ 'precgetexpr']
2162  call assert_equal(l, g:acmds)
2163
2164  let g:acmds = []
2165  enew! | call append(0, "F2:10:Line 10")
2166  cbuffer!
2167  enew! | call append(0, "F2:20:Line 20")
2168  cgetbuffer
2169  enew! | call append(0, "F2:30:Line 30")
2170  caddbuffer
2171  new
2172  let bnum = bufnr('%')
2173  bunload
2174  exe 'silent! cbuffer! ' . bnum
2175  exe 'silent! cgetbuffer ' . bnum
2176  exe 'silent! caddbuffer ' . bnum
2177  enew!
2178  let l = ['precbuffer',
2179	      \ 'postcbuffer',
2180	      \ 'precgetbuffer',
2181	      \ 'postcgetbuffer',
2182	      \ 'precaddbuffer',
2183	      \ 'postcaddbuffer',
2184	      \ 'precbuffer',
2185	      \ 'precgetbuffer',
2186	      \ 'precaddbuffer']
2187  call assert_equal(l, g:acmds)
2188
2189  call writefile(['Xtest:1:Line1'], 'Xtest')
2190  call writefile([], 'Xempty')
2191  let g:acmds = []
2192  cfile Xtest
2193  caddfile Xtest
2194  cgetfile Xtest
2195  cfile Xempty
2196  caddfile Xempty
2197  cgetfile Xempty
2198  silent! cfile do_not_exist
2199  silent! caddfile do_not_exist
2200  silent! cgetfile do_not_exist
2201  let l = ['precfile',
2202	      \ 'postcfile',
2203	      \ 'precaddfile',
2204	      \ 'postcaddfile',
2205	      \ 'precgetfile',
2206	      \ 'postcgetfile',
2207	      \ 'precfile',
2208	      \ 'postcfile',
2209	      \ 'precaddfile',
2210	      \ 'postcaddfile',
2211	      \ 'precgetfile',
2212	      \ 'postcgetfile',
2213	      \ 'precfile',
2214	      \ 'postcfile',
2215	      \ 'precaddfile',
2216	      \ 'postcaddfile',
2217	      \ 'precgetfile',
2218	      \ 'postcgetfile']
2219  call assert_equal(l, g:acmds)
2220
2221  let g:acmds = []
2222  helpgrep quickfix
2223  silent! helpgrep non_existing_help_topic
2224  vimgrep test Xtest
2225  vimgrepadd test Xtest
2226  silent! vimgrep non_existing_test Xtest
2227  silent! vimgrepadd non_existing_test Xtest
2228  set makeprg=
2229  silent! make
2230  set makeprg&
2231  let l = ['prehelpgrep',
2232	      \ 'posthelpgrep',
2233	      \ 'prehelpgrep',
2234	      \ 'posthelpgrep',
2235	      \ 'previmgrep',
2236	      \ 'postvimgrep',
2237	      \ 'previmgrepadd',
2238	      \ 'postvimgrepadd',
2239	      \ 'previmgrep',
2240	      \ 'postvimgrep',
2241	      \ 'previmgrepadd',
2242	      \ 'postvimgrepadd',
2243	      \ 'premake',
2244	      \ 'postmake']
2245  call assert_equal(l, g:acmds)
2246
2247  if has('unix')
2248    " Run this test only on Unix-like systems. The grepprg may not be set on
2249    " non-Unix systems.
2250    " The following lines are used for the grep test. Don't remove.
2251    " Grep_Autocmd_Text: Match 1
2252    " GrepAdd_Autocmd_Text: Match 2
2253    let g:acmds = []
2254    silent grep Grep_Autocmd_Text test_quickfix.vim
2255    silent grepadd GrepAdd_Autocmd_Text test_quickfix.vim
2256    silent grep abc123def Xtest
2257    silent grepadd abc123def Xtest
2258    let l = ['pregrep',
2259		\ 'postgrep',
2260		\ 'pregrepadd',
2261		\ 'postgrepadd',
2262		\ 'pregrep',
2263		\ 'postgrep',
2264		\ 'pregrepadd',
2265		\ 'postgrepadd']
2266    call assert_equal(l, g:acmds)
2267  endif
2268
2269  call delete('Xtest')
2270  call delete('Xempty')
2271  au! QuickFixCmdPre
2272  au! QuickFixCmdPost
2273endfunc
2274
2275func Test_Autocmd_Exception()
2276  set efm=%m
2277  lgetexpr '?'
2278
2279  try
2280    call DoesNotExit()
2281  catch
2282    lgetexpr '1'
2283  finally
2284    lgetexpr '1'
2285  endtry
2286
2287  call assert_equal('1', getloclist(0)[0].text)
2288
2289  set efm&vim
2290endfunc
2291
2292func Test_caddbuffer_wrong()
2293  " This used to cause a memory access in freed memory.
2294  let save_efm = &efm
2295  set efm=%EEEE%m,%WWWW,%+CCCC%>%#,%GGGG%.#
2296  cgetexpr ['WWWW', 'EEEE', 'CCCC']
2297  let &efm = save_efm
2298  caddbuffer
2299  bwipe!
2300endfunc
2301
2302func Test_caddexpr_wrong()
2303  " This used to cause a memory access in freed memory.
2304  cbuffer
2305  cbuffer
2306  copen
2307  let save_efm = &efm
2308  set efm=%
2309  call assert_fails('caddexpr ""', 'E376:')
2310  let &efm = save_efm
2311endfunc
2312
2313func Test_dirstack_cleanup()
2314  " This used to cause a memory access in freed memory.
2315  let save_efm = &efm
2316  lexpr '0'
2317  lopen
2318  fun X(c)
2319    let save_efm=&efm
2320    set efm=%D%f
2321    if a:c == 'c'
2322      caddexpr '::'
2323    else
2324      laddexpr ':0:0'
2325    endif
2326    let &efm=save_efm
2327  endfun
2328  call X('c')
2329  call X('l')
2330  call setqflist([], 'r')
2331  caddbuffer
2332  let &efm = save_efm
2333endfunc
2334
2335" Tests for jumping to entries from the location list window and quickfix
2336" window
2337func Test_cwindow_jump()
2338  set efm=%f%%%l%%%m
2339  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2340  lopen | only
2341  lfirst
2342  call assert_true(winnr('$') == 2)
2343  call assert_true(winnr() == 1)
2344  " Location list for the new window should be set
2345  call assert_true(getloclist(0)[2].text == 'Line 30')
2346
2347  " Open a scratch buffer
2348  " Open a new window and create a location list
2349  " Open the location list window and close the other window
2350  " Jump to an entry.
2351  " Should create a new window and jump to the entry. The scrtach buffer
2352  " should not be used.
2353  enew | only
2354  set buftype=nofile
2355  below new
2356  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2357  lopen
2358  2wincmd c
2359  lnext
2360  call assert_true(winnr('$') == 3)
2361  call assert_true(winnr() == 2)
2362
2363  " Open two windows with two different location lists
2364  " Open the location list window and close the previous window
2365  " Jump to an entry in the location list window
2366  " Should open the file in the first window and not set the location list.
2367  enew | only
2368  lgetexpr ["F1%5%Line 5"]
2369  below new
2370  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2371  lopen
2372  2wincmd c
2373  lnext
2374  call assert_true(winnr() == 1)
2375  call assert_true(getloclist(0)[0].text == 'Line 5')
2376
2377  enew | only
2378  cgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2379  copen
2380  cnext
2381  call assert_true(winnr('$') == 2)
2382  call assert_true(winnr() == 1)
2383
2384  enew | only
2385  set efm&vim
2386endfunc
2387
2388func XvimgrepTests(cchar)
2389  call s:setup_commands(a:cchar)
2390
2391  call writefile(['Editor:VIM vim',
2392	      \ 'Editor:Emacs EmAcS',
2393	      \ 'Editor:Notepad NOTEPAD'], 'Xtestfile1')
2394  call writefile(['Linux', 'MacOS', 'MS-Windows'], 'Xtestfile2')
2395
2396  " Error cases
2397  call assert_fails('Xvimgrep /abc *', 'E682:')
2398
2399  let @/=''
2400  call assert_fails('Xvimgrep // *', 'E35:')
2401
2402  call assert_fails('Xvimgrep abc', 'E683:')
2403  call assert_fails('Xvimgrep a1b2c3 Xtestfile1', 'E480:')
2404  call assert_fails('Xvimgrep pat Xa1b2c3', 'E480:')
2405
2406  Xexpr ""
2407  Xvimgrepadd Notepad Xtestfile1
2408  Xvimgrepadd MacOS Xtestfile2
2409  let l = g:Xgetlist()
2410  call assert_equal(2, len(l))
2411  call assert_equal('Editor:Notepad NOTEPAD', l[0].text)
2412
2413  Xvimgrep #\cvim#g Xtestfile?
2414  let l = g:Xgetlist()
2415  call assert_equal(2, len(l))
2416  call assert_equal(8, l[0].col)
2417  call assert_equal(12, l[1].col)
2418
2419  1Xvimgrep ?Editor? Xtestfile*
2420  let l = g:Xgetlist()
2421  call assert_equal(1, len(l))
2422  call assert_equal('Editor:VIM vim', l[0].text)
2423
2424  edit +3 Xtestfile2
2425  Xvimgrep +\cemacs+j Xtestfile1
2426  let l = g:Xgetlist()
2427  call assert_equal('Xtestfile2', bufname(''))
2428  call assert_equal('Editor:Emacs EmAcS', l[0].text)
2429
2430  " Test for unloading a buffer after vimgrep searched the buffer
2431  %bwipe
2432  Xvimgrep /Editor/j Xtestfile*
2433  call assert_equal(0, getbufinfo('Xtestfile1')[0].loaded)
2434  call assert_equal([], getbufinfo('Xtestfile2'))
2435
2436  call delete('Xtestfile1')
2437  call delete('Xtestfile2')
2438endfunc
2439
2440" Tests for the :vimgrep command
2441func Test_vimgrep()
2442  call XvimgrepTests('c')
2443  call XvimgrepTests('l')
2444endfunc
2445
2446" Test for incsearch highlighting of the :vimgrep pattern
2447" This test used to cause "E315: ml_get: invalid lnum" errors.
2448func Test_vimgrep_incsearch()
2449  enew
2450  set incsearch
2451  call test_override("char_avail", 1)
2452
2453  call feedkeys(":2vimgrep assert test_quickfix.vim test_cdo.vim\<CR>", "ntx")
2454  let l = getqflist()
2455  call assert_equal(2, len(l))
2456
2457  call test_override("ALL", 0)
2458  set noincsearch
2459endfunc
2460
2461func XfreeTests(cchar)
2462  call s:setup_commands(a:cchar)
2463
2464  enew | only
2465
2466  " Deleting the quickfix stack should work even When the current list is
2467  " somewhere in the middle of the stack
2468  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2469  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2470  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2471  Xolder
2472  call g:Xsetlist([], 'f')
2473  call assert_equal(0, len(g:Xgetlist()))
2474
2475  " After deleting the stack, adding a new list should create a stack with a
2476  " single list.
2477  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2478  call assert_equal(1, g:Xgetlist({'all':1}).nr)
2479
2480  " Deleting the stack from a quickfix window should update/clear the
2481  " quickfix/location list window.
2482  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2483  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2484  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2485  Xolder
2486  Xwindow
2487  call g:Xsetlist([], 'f')
2488  call assert_equal(2, winnr('$'))
2489  call assert_equal(1, line('$'))
2490  Xclose
2491
2492  " Deleting the stack from a non-quickfix window should update/clear the
2493  " quickfix/location list window.
2494  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2495  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2496  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2497  Xolder
2498  Xwindow
2499  wincmd p
2500  call g:Xsetlist([], 'f')
2501  call assert_equal(0, len(g:Xgetlist()))
2502  wincmd p
2503  call assert_equal(2, winnr('$'))
2504  call assert_equal(1, line('$'))
2505
2506  " After deleting the location list stack, if the location list window is
2507  " opened, then a new location list should be created. So opening the
2508  " location list window again should not create a new window.
2509  if a:cchar == 'l'
2510      lexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2511      wincmd p
2512      lopen
2513      call assert_equal(2, winnr('$'))
2514  endif
2515  Xclose
2516endfunc
2517
2518" Tests for the quickfix free functionality
2519func Test_qf_free()
2520  call XfreeTests('c')
2521  call XfreeTests('l')
2522endfunc
2523
2524" Test for buffer overflow when parsing lines and adding new entries to
2525" the quickfix list.
2526func Test_bufoverflow()
2527  set efm=%f:%l:%m
2528  cgetexpr ['File1:100:' . repeat('x', 1025)]
2529
2530  set efm=%+GCompiler:\ %.%#,%f:%l:%m
2531  cgetexpr ['Compiler: ' . repeat('a', 1015), 'File1:10:Hello World']
2532
2533  set efm=%DEntering\ directory\ %f,%f:%l:%m
2534  cgetexpr ['Entering directory ' . repeat('a', 1006),
2535	      \ 'File1:10:Hello World']
2536  set efm&vim
2537endfunc
2538
2539" Tests for getting the quickfix stack size
2540func XsizeTests(cchar)
2541  call s:setup_commands(a:cchar)
2542
2543  call g:Xsetlist([], 'f')
2544  call assert_equal(0, g:Xgetlist({'nr':'$'}).nr)
2545  call assert_equal('', g:Xgetlist({'nr':'$', 'all':1}).title)
2546  call assert_equal(0, g:Xgetlist({'nr':0}).nr)
2547
2548  Xexpr "File1:10:Line1"
2549  Xexpr "File2:20:Line2"
2550  Xexpr "File3:30:Line3"
2551  Xolder | Xolder
2552  call assert_equal(3, g:Xgetlist({'nr':'$'}).nr)
2553  call g:Xsetlist([], 'f')
2554
2555  Xexpr "File1:10:Line1"
2556  Xexpr "File2:20:Line2"
2557  Xexpr "File3:30:Line3"
2558  Xolder | Xolder
2559  call g:Xsetlist([], 'a', {'nr':'$', 'title':'Compiler'})
2560  call assert_equal('Compiler', g:Xgetlist({'nr':3, 'all':1}).title)
2561endfunc
2562
2563func Test_Qf_Size()
2564  call XsizeTests('c')
2565  call XsizeTests('l')
2566endfunc
2567
2568func Test_cclose_from_copen()
2569    augroup QF_Test
2570	au!
2571        au FileType qf :call assert_fails(':cclose', 'E788')
2572    augroup END
2573    copen
2574    augroup QF_Test
2575	au!
2576    augroup END
2577    augroup! QF_Test
2578endfunc
2579
2580func Test_cclose_in_autocmd()
2581  " Problem is only triggered if "starting" is zero, so that the OptionsSet
2582  " event will be triggered.
2583  call test_override('starting', 1)
2584  augroup QF_Test
2585    au!
2586    au FileType qf :call assert_fails(':cclose', 'E788')
2587  augroup END
2588  copen
2589  augroup QF_Test
2590    au!
2591  augroup END
2592  augroup! QF_Test
2593  call test_override('starting', 0)
2594endfunc
2595
2596" Check that ":file" without an argument is possible even when "curbuf_lock"
2597" is set.
2598func Test_file_from_copen()
2599  " Works without argument.
2600  augroup QF_Test
2601    au!
2602    au FileType qf file
2603  augroup END
2604  copen
2605
2606  augroup QF_Test
2607    au!
2608  augroup END
2609  cclose
2610
2611  " Fails with argument.
2612  augroup QF_Test
2613    au!
2614    au FileType qf call assert_fails(':file foo', 'E788')
2615  augroup END
2616  copen
2617  augroup QF_Test
2618    au!
2619  augroup END
2620  cclose
2621
2622  augroup! QF_Test
2623endfunction
2624
2625func Test_resize_from_copen()
2626    augroup QF_Test
2627	au!
2628        au FileType qf resize 5
2629    augroup END
2630    try
2631	" This should succeed without any exception.  No other buffers are
2632	" involved in the autocmd.
2633	copen
2634    finally
2635	augroup QF_Test
2636	    au!
2637	augroup END
2638	augroup! QF_Test
2639    endtry
2640endfunc
2641
2642" Tests for the quickfix buffer b:changedtick variable
2643func Xchangedtick_tests(cchar)
2644  call s:setup_commands(a:cchar)
2645
2646  new | only
2647
2648  Xexpr "" | Xexpr "" | Xexpr ""
2649
2650  Xopen
2651  Xolder
2652  Xolder
2653  Xaddexpr "F1:10:Line10"
2654  Xaddexpr "F2:20:Line20"
2655  call g:Xsetlist([{"filename":"F3", "lnum":30, "text":"Line30"}], 'a')
2656  call g:Xsetlist([], 'f')
2657  call assert_equal(8, getbufvar('%', 'changedtick'))
2658  Xclose
2659endfunc
2660
2661func Test_changedtick()
2662  call Xchangedtick_tests('c')
2663  call Xchangedtick_tests('l')
2664endfunc
2665
2666" Tests for parsing an expression using setqflist()
2667func Xsetexpr_tests(cchar)
2668  call s:setup_commands(a:cchar)
2669
2670  let t = ["File1:10:Line10", "File1:20:Line20"]
2671  call g:Xsetlist([], ' ', {'lines' : t})
2672  call g:Xsetlist([], 'a', {'lines' : ["File1:30:Line30"]})
2673
2674  let l = g:Xgetlist()
2675  call assert_equal(3, len(l))
2676  call assert_equal(20, l[1].lnum)
2677  call assert_equal('Line30', l[2].text)
2678  call g:Xsetlist([], 'r', {'lines' : ["File2:5:Line5"]})
2679  let l = g:Xgetlist()
2680  call assert_equal(1, len(l))
2681  call assert_equal('Line5', l[0].text)
2682  call assert_equal(-1, g:Xsetlist([], 'a', {'lines' : 10}))
2683  call assert_equal(-1, g:Xsetlist([], 'a', {'lines' : "F1:10:L10"}))
2684
2685  call g:Xsetlist([], 'f')
2686  " Add entries to multiple lists
2687  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["File1:10:Line10"]})
2688  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["File2:20:Line20"]})
2689  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["File1:15:Line15"]})
2690  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["File2:25:Line25"]})
2691  call assert_equal('Line15', g:Xgetlist({'nr':1, 'items':1}).items[1].text)
2692  call assert_equal('Line25', g:Xgetlist({'nr':2, 'items':1}).items[1].text)
2693
2694  " Adding entries using a custom efm
2695  set efm&
2696  call g:Xsetlist([], ' ', {'efm' : '%f#%l#%m',
2697				\ 'lines' : ["F1#10#L10", "F2#20#L20"]})
2698  call assert_equal(20, g:Xgetlist({'items':1}).items[1].lnum)
2699  call g:Xsetlist([], 'a', {'efm' : '%f#%l#%m', 'lines' : ["F3:30:L30"]})
2700  call assert_equal('F3:30:L30', g:Xgetlist({'items':1}).items[2].text)
2701  call assert_equal(20, g:Xgetlist({'items':1}).items[1].lnum)
2702  call assert_equal(-1, g:Xsetlist([], 'a', {'efm' : [],
2703				\ 'lines' : ['F1:10:L10']}))
2704endfunc
2705
2706func Test_setexpr()
2707  call Xsetexpr_tests('c')
2708  call Xsetexpr_tests('l')
2709endfunc
2710
2711" Tests for per quickfix/location list directory stack
2712func Xmultidirstack_tests(cchar)
2713  call s:setup_commands(a:cchar)
2714
2715  call g:Xsetlist([], 'f')
2716  Xexpr "" | Xexpr ""
2717
2718  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["Entering dir 'Xone/a'"]})
2719  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["Entering dir 'Xtwo/a'"]})
2720  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["one.txt:3:one one one"]})
2721  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["two.txt:5:two two two"]})
2722
2723  let l1 = g:Xgetlist({'nr':1, 'items':1})
2724  let l2 = g:Xgetlist({'nr':2, 'items':1})
2725  call assert_equal('Xone/a/one.txt', bufname(l1.items[1].bufnr))
2726  call assert_equal(3, l1.items[1].lnum)
2727  call assert_equal('Xtwo/a/two.txt', bufname(l2.items[1].bufnr))
2728  call assert_equal(5, l2.items[1].lnum)
2729endfunc
2730
2731func Test_multidirstack()
2732  call mkdir('Xone/a', 'p')
2733  call mkdir('Xtwo/a', 'p')
2734  let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7']
2735  call writefile(lines, 'Xone/a/one.txt')
2736  call writefile(lines, 'Xtwo/a/two.txt')
2737  let save_efm = &efm
2738  set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f'
2739
2740  call Xmultidirstack_tests('c')
2741  call Xmultidirstack_tests('l')
2742
2743  let &efm = save_efm
2744  call delete('Xone', 'rf')
2745  call delete('Xtwo', 'rf')
2746endfunc
2747
2748" Tests for per quickfix/location list file stack
2749func Xmultifilestack_tests(cchar)
2750  call s:setup_commands(a:cchar)
2751
2752  call g:Xsetlist([], 'f')
2753  Xexpr "" | Xexpr ""
2754
2755  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["[one.txt]"]})
2756  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["[two.txt]"]})
2757  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["(3,5) one one one"]})
2758  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["(5,9) two two two"]})
2759
2760  let l1 = g:Xgetlist({'nr':1, 'items':1})
2761  let l2 = g:Xgetlist({'nr':2, 'items':1})
2762  call assert_equal('one.txt', bufname(l1.items[1].bufnr))
2763  call assert_equal(3, l1.items[1].lnum)
2764  call assert_equal('two.txt', bufname(l2.items[1].bufnr))
2765  call assert_equal(5, l2.items[1].lnum)
2766
2767  " Test for start of a new error line in the same line where a previous
2768  " error line ends with a file stack.
2769  let efm_val = 'Error\ l%l\ in\ %f,'
2770  let efm_val .= '%-P%>(%f%r,Error\ l%l\ in\ %m,%-Q)%r'
2771  let l = g:Xgetlist({'lines' : [
2772	      \ '(one.txt',
2773	      \ 'Error l4 in one.txt',
2774	      \ ') (two.txt',
2775	      \ 'Error l6 in two.txt',
2776	      \ ')',
2777	      \ 'Error l8 in one.txt'
2778	      \ ], 'efm' : efm_val})
2779  call assert_equal(3, len(l.items))
2780  call assert_equal('one.txt', bufname(l.items[0].bufnr))
2781  call assert_equal(4, l.items[0].lnum)
2782  call assert_equal('one.txt', l.items[0].text)
2783  call assert_equal('two.txt', bufname(l.items[1].bufnr))
2784  call assert_equal(6, l.items[1].lnum)
2785  call assert_equal('two.txt', l.items[1].text)
2786  call assert_equal('one.txt', bufname(l.items[2].bufnr))
2787  call assert_equal(8, l.items[2].lnum)
2788  call assert_equal('', l.items[2].text)
2789endfunc
2790
2791func Test_multifilestack()
2792  let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7']
2793  call writefile(lines, 'one.txt')
2794  call writefile(lines, 'two.txt')
2795  let save_efm = &efm
2796  set efm=%+P[%f],(%l\\,%c)\ %m,%-Q
2797
2798  call Xmultifilestack_tests('c')
2799  call Xmultifilestack_tests('l')
2800
2801  let &efm = save_efm
2802  call delete('one.txt')
2803  call delete('two.txt')
2804endfunc
2805
2806" Tests for per buffer 'efm' setting
2807func Test_perbuf_efm()
2808  call writefile(["File1-10-Line10"], 'one.txt')
2809  call writefile(["File2#20#Line20"], 'two.txt')
2810  set efm=%f#%l#%m
2811  new | only
2812  new
2813  setlocal efm=%f-%l-%m
2814  cfile one.txt
2815  wincmd w
2816  caddfile two.txt
2817
2818  let l = getqflist()
2819  call assert_equal(10, l[0].lnum)
2820  call assert_equal('Line20', l[1].text)
2821
2822  set efm&
2823  new | only
2824  call delete('one.txt')
2825  call delete('two.txt')
2826endfunc
2827
2828" Open multiple help windows using ":lhelpgrep
2829" This test used to crash Vim
2830func Test_Multi_LL_Help()
2831    new | only
2832    lhelpgrep window
2833    lopen
2834    e#
2835    lhelpgrep buffer
2836    call assert_equal(3, winnr('$'))
2837    call assert_true(len(getloclist(1)) != 0)
2838    call assert_true(len(getloclist(2)) != 0)
2839    new | only
2840endfunc
2841
2842" Tests for adding new quickfix lists using setqflist()
2843func XaddQf_tests(cchar)
2844  call s:setup_commands(a:cchar)
2845
2846  " Create a new list using ' ' for action
2847  call g:Xsetlist([], 'f')
2848  call g:Xsetlist([], ' ', {'title' : 'Test1'})
2849  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2850  call assert_equal(1, l.nr)
2851  call assert_equal('Test1', l.title)
2852
2853  " Create a new list using ' ' for action and '$' for 'nr'
2854  call g:Xsetlist([], 'f')
2855  call g:Xsetlist([], ' ', {'title' : 'Test2', 'nr' : '$'})
2856  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2857  call assert_equal(1, l.nr)
2858  call assert_equal('Test2', l.title)
2859
2860  " Create a new list using 'a' for action
2861  call g:Xsetlist([], 'f')
2862  call g:Xsetlist([], 'a', {'title' : 'Test3'})
2863  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2864  call assert_equal(1, l.nr)
2865  call assert_equal('Test3', l.title)
2866
2867  " Create a new list using 'a' for action and '$' for 'nr'
2868  call g:Xsetlist([], 'f')
2869  call g:Xsetlist([], 'a', {'title' : 'Test3', 'nr' : '$'})
2870  call g:Xsetlist([], 'a', {'title' : 'Test4'})
2871  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2872  call assert_equal(1, l.nr)
2873  call assert_equal('Test4', l.title)
2874
2875  " Adding a quickfix list should remove all the lists following the current
2876  " list.
2877  Xexpr "" | Xexpr "" | Xexpr ""
2878  silent! 10Xolder
2879  call g:Xsetlist([], ' ', {'title' : 'Test5'})
2880  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2881  call assert_equal(2, l.nr)
2882  call assert_equal('Test5', l.title)
2883
2884  " Add a quickfix list using '$' as the list number.
2885  let lastqf = g:Xgetlist({'nr':'$'}).nr
2886  silent! 99Xolder
2887  call g:Xsetlist([], ' ', {'nr' : '$', 'title' : 'Test6'})
2888  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2889  call assert_equal(lastqf + 1, l.nr)
2890  call assert_equal('Test6', l.title)
2891
2892  " Add a quickfix list using 'nr' set to one more than the quickfix
2893  " list size.
2894  let lastqf = g:Xgetlist({'nr':'$'}).nr
2895  silent! 99Xolder
2896  call g:Xsetlist([], ' ', {'nr' : lastqf + 1, 'title' : 'Test7'})
2897  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2898  call assert_equal(lastqf + 1, l.nr)
2899  call assert_equal('Test7', l.title)
2900
2901  " Add a quickfix list to a stack with 10 lists using 'nr' set to '$'
2902  exe repeat('Xexpr "" |', 9) . 'Xexpr ""'
2903  silent! 99Xolder
2904  call g:Xsetlist([], ' ', {'nr' : '$', 'title' : 'Test8'})
2905  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2906  call assert_equal(10, l.nr)
2907  call assert_equal('Test8', l.title)
2908
2909  " Add a quickfix list using 'nr' set to a value greater than 10
2910  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : 12, 'title' : 'Test9'}))
2911
2912  " Try adding a quickfix list with 'nr' set to a value greater than the
2913  " quickfix list size but less than 10.
2914  call g:Xsetlist([], 'f')
2915  Xexpr "" | Xexpr "" | Xexpr ""
2916  silent! 99Xolder
2917  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : 8, 'title' : 'Test10'}))
2918
2919  " Add a quickfix list using 'nr' set to a some string or list
2920  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : [1,2], 'title' : 'Test11'}))
2921endfunc
2922
2923func Test_add_qf()
2924  call XaddQf_tests('c')
2925  call XaddQf_tests('l')
2926endfunc
2927
2928" Test for getting the quickfix list items from some text without modifying
2929" the quickfix stack
2930func XgetListFromLines(cchar)
2931  call s:setup_commands(a:cchar)
2932  call g:Xsetlist([], 'f')
2933
2934  let l = g:Xgetlist({'lines' : ["File2:20:Line20", "File2:30:Line30"]}).items
2935  call assert_equal(2, len(l))
2936  call assert_equal(30, l[1].lnum)
2937
2938  call assert_equal({}, g:Xgetlist({'lines' : 10}))
2939  call assert_equal({}, g:Xgetlist({'lines' : 'File1:10:Line10'}))
2940  call assert_equal([], g:Xgetlist({'lines' : []}).items)
2941  call assert_equal([], g:Xgetlist({'lines' : [10, 20]}).items)
2942
2943  " Parse text using a custom efm
2944  set efm&
2945  let l = g:Xgetlist({'lines':['File3#30#Line30'], 'efm' : '%f#%l#%m'}).items
2946  call assert_equal('Line30', l[0].text)
2947  let l = g:Xgetlist({'lines':['File3:30:Line30'], 'efm' : '%f-%l-%m'}).items
2948  call assert_equal('File3:30:Line30', l[0].text)
2949  let l = g:Xgetlist({'lines':['File3:30:Line30'], 'efm' : [1,2]})
2950  call assert_equal({}, l)
2951  call assert_fails("call g:Xgetlist({'lines':['abc'], 'efm':'%2'})", 'E376:')
2952  call assert_fails("call g:Xgetlist({'lines':['abc'], 'efm':''})", 'E378:')
2953
2954  " Make sure that the quickfix stack is not modified
2955  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
2956endfunc
2957
2958func Test_get_list_from_lines()
2959  call XgetListFromLines('c')
2960  call XgetListFromLines('l')
2961endfunc
2962
2963" Tests for the quickfix list id
2964func Xqfid_tests(cchar)
2965  call s:setup_commands(a:cchar)
2966
2967  call g:Xsetlist([], 'f')
2968  call assert_equal(0, g:Xgetlist({'id':0}).id)
2969  Xexpr ''
2970  let start_id = g:Xgetlist({'id' : 0}).id
2971  Xexpr '' | Xexpr ''
2972  Xolder
2973  call assert_equal(start_id, g:Xgetlist({'id':0, 'nr':1}).id)
2974  call assert_equal(start_id + 1, g:Xgetlist({'id':0, 'nr':0}).id)
2975  call assert_equal(start_id + 2, g:Xgetlist({'id':0, 'nr':'$'}).id)
2976  call assert_equal(0, g:Xgetlist({'id':0, 'nr':99}).id)
2977  call assert_equal(2, g:Xgetlist({'id':start_id + 1, 'nr':0}).nr)
2978  call assert_equal(0, g:Xgetlist({'id':99, 'nr':0}).id)
2979  call assert_equal(0, g:Xgetlist({'id':"abc", 'nr':0}).id)
2980
2981  call g:Xsetlist([], 'a', {'id':start_id, 'context':[1,2]})
2982  call assert_equal([1,2], g:Xgetlist({'nr':1, 'context':1}).context)
2983  call g:Xsetlist([], 'a', {'id':start_id+1, 'lines':['F1:10:L10']})
2984  call assert_equal('L10', g:Xgetlist({'nr':2, 'items':1}).items[0].text)
2985  call assert_equal(-1, g:Xsetlist([], 'a', {'id':999, 'title':'Vim'}))
2986  call assert_equal(-1, g:Xsetlist([], 'a', {'id':'abc', 'title':'Vim'}))
2987
2988  let qfid = g:Xgetlist({'id':0, 'nr':0})
2989  call g:Xsetlist([], 'f')
2990  call assert_equal(0, g:Xgetlist({'id':qfid, 'nr':0}).id)
2991endfunc
2992
2993func Test_qf_id()
2994  call Xqfid_tests('c')
2995  call Xqfid_tests('l')
2996endfunc
2997
2998func Xqfjump_tests(cchar)
2999  call s:setup_commands(a:cchar)
3000
3001  call writefile(["Line1\tFoo", "Line2"], 'F1')
3002  call writefile(["Line1\tBar", "Line2"], 'F2')
3003  call writefile(["Line1\tBaz", "Line2"], 'F3')
3004
3005  call g:Xsetlist([], 'f')
3006
3007  " Tests for
3008  "   Jumping to a line using a pattern
3009  "   Jumping to a column greater than the last column in a line
3010  "   Jumping to a line greater than the last line in the file
3011  let l = []
3012  for i in range(1, 7)
3013    call add(l, {})
3014  endfor
3015  let l[0].filename='F1'
3016  let l[0].pattern='Line1'
3017  let l[1].filename='F2'
3018  let l[1].pattern='Line1'
3019  let l[2].filename='F3'
3020  let l[2].pattern='Line1'
3021  let l[3].filename='F3'
3022  let l[3].lnum=1
3023  let l[3].col=9
3024  let l[3].vcol=1
3025  let l[4].filename='F3'
3026  let l[4].lnum=99
3027  let l[5].filename='F3'
3028  let l[5].lnum=1
3029  let l[5].col=99
3030  let l[5].vcol=1
3031  let l[6].filename='F3'
3032  let l[6].pattern='abcxyz'
3033
3034  call g:Xsetlist([], ' ', {'items' : l})
3035  Xopen | only
3036  2Xnext
3037  call assert_equal(3, g:Xgetlist({'idx' : 0}).idx)
3038  call assert_equal('F3', bufname('%'))
3039  Xnext
3040  call assert_equal(7, col('.'))
3041  Xnext
3042  call assert_equal(2, line('.'))
3043  Xnext
3044  call assert_equal(9, col('.'))
3045  2
3046  Xnext
3047  call assert_equal(2, line('.'))
3048
3049  if a:cchar == 'l'
3050    " When jumping to a location list entry in the location list window and
3051    " no usable windows are available, then a new window should be opened.
3052    enew! | new | only
3053    call g:Xsetlist([], 'f')
3054    setlocal buftype=nofile
3055    new
3056    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']})
3057    Xopen
3058    let winid = win_getid()
3059    wincmd p
3060    close
3061    call win_gotoid(winid)
3062    Xnext
3063    call assert_equal(3, winnr('$'))
3064    call assert_equal(1, winnr())
3065    call assert_equal(2, line('.'))
3066
3067    " When jumping to an entry in the location list window and the window
3068    " associated with the location list is not present and a window containing
3069    " the file is already present, then that window should be used.
3070    close
3071    belowright new
3072    call g:Xsetlist([], 'f')
3073    edit F3
3074    call win_gotoid(winid)
3075    Xlast
3076    call assert_equal(3, winnr())
3077    call assert_equal(6, g:Xgetlist({'size' : 1}).size)
3078    call assert_equal(winid, g:Xgetlist({'winid' : 1}).winid)
3079  endif
3080
3081  " Cleanup
3082  enew!
3083  new | only
3084
3085  call delete('F1')
3086  call delete('F2')
3087  call delete('F3')
3088endfunc
3089
3090func Test_qfjump()
3091  call Xqfjump_tests('c')
3092  call Xqfjump_tests('l')
3093endfunc
3094
3095" Tests for the getqflist() and getloclist() functions when the list is not
3096" present or is empty
3097func Xgetlist_empty_tests(cchar)
3098  call s:setup_commands(a:cchar)
3099
3100  " Empty quickfix stack
3101  call g:Xsetlist([], 'f')
3102  call assert_equal('', g:Xgetlist({'context' : 0}).context)
3103  call assert_equal(0, g:Xgetlist({'id' : 0}).id)
3104  call assert_equal(0, g:Xgetlist({'idx' : 0}).idx)
3105  call assert_equal([], g:Xgetlist({'items' : 0}).items)
3106  call assert_equal(0, g:Xgetlist({'nr' : 0}).nr)
3107  call assert_equal(0, g:Xgetlist({'size' : 0}).size)
3108  call assert_equal('', g:Xgetlist({'title' : 0}).title)
3109  call assert_equal(0, g:Xgetlist({'winid' : 0}).winid)
3110  call assert_equal(0, g:Xgetlist({'changedtick' : 0}).changedtick)
3111  if a:cchar == 'c'
3112    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0,
3113		  \ 'items' : [], 'nr' : 0, 'size' : 0,
3114		  \ 'title' : '', 'winid' : 0, 'changedtick': 0},
3115		  \ g:Xgetlist({'all' : 0}))
3116  else
3117    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0,
3118		\ 'items' : [], 'nr' : 0, 'size' : 0, 'title' : '',
3119		\ 'winid' : 0, 'changedtick': 0, 'filewinid' : 0},
3120		\ g:Xgetlist({'all' : 0}))
3121  endif
3122
3123  " Quickfix window with empty stack
3124  silent! Xopen
3125  let qfwinid = (a:cchar == 'c') ? win_getid() : 0
3126  call assert_equal(qfwinid, g:Xgetlist({'winid' : 0}).winid)
3127  Xclose
3128
3129  " Empty quickfix list
3130  Xexpr ""
3131  call assert_equal('', g:Xgetlist({'context' : 0}).context)
3132  call assert_notequal(0, g:Xgetlist({'id' : 0}).id)
3133  call assert_equal(0, g:Xgetlist({'idx' : 0}).idx)
3134  call assert_equal([], g:Xgetlist({'items' : 0}).items)
3135  call assert_notequal(0, g:Xgetlist({'nr' : 0}).nr)
3136  call assert_equal(0, g:Xgetlist({'size' : 0}).size)
3137  call assert_notequal('', g:Xgetlist({'title' : 0}).title)
3138  call assert_equal(0, g:Xgetlist({'winid' : 0}).winid)
3139  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3140
3141  let qfid = g:Xgetlist({'id' : 0}).id
3142  call g:Xsetlist([], 'f')
3143
3144  " Non-existing quickfix identifier
3145  call assert_equal('', g:Xgetlist({'id' : qfid, 'context' : 0}).context)
3146  call assert_equal(0, g:Xgetlist({'id' : qfid}).id)
3147  call assert_equal(0, g:Xgetlist({'id' : qfid, 'idx' : 0}).idx)
3148  call assert_equal([], g:Xgetlist({'id' : qfid, 'items' : 0}).items)
3149  call assert_equal(0, g:Xgetlist({'id' : qfid, 'nr' : 0}).nr)
3150  call assert_equal(0, g:Xgetlist({'id' : qfid, 'size' : 0}).size)
3151  call assert_equal('', g:Xgetlist({'id' : qfid, 'title' : 0}).title)
3152  call assert_equal(0, g:Xgetlist({'id' : qfid, 'winid' : 0}).winid)
3153  call assert_equal(0, g:Xgetlist({'id' : qfid, 'changedtick' : 0}).changedtick)
3154  if a:cchar == 'c'
3155    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
3156		\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
3157		\ 'changedtick' : 0}, g:Xgetlist({'id' : qfid, 'all' : 0}))
3158  else
3159    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
3160		\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
3161		\ 'changedtick' : 0, 'filewinid' : 0},
3162		\ g:Xgetlist({'id' : qfid, 'all' : 0}))
3163  endif
3164
3165  " Non-existing quickfix list number
3166  call assert_equal('', g:Xgetlist({'nr' : 5, 'context' : 0}).context)
3167  call assert_equal(0, g:Xgetlist({'nr' : 5}).nr)
3168  call assert_equal(0, g:Xgetlist({'nr' : 5, 'idx' : 0}).idx)
3169  call assert_equal([], g:Xgetlist({'nr' : 5, 'items' : 0}).items)
3170  call assert_equal(0, g:Xgetlist({'nr' : 5, 'id' : 0}).id)
3171  call assert_equal(0, g:Xgetlist({'nr' : 5, 'size' : 0}).size)
3172  call assert_equal('', g:Xgetlist({'nr' : 5, 'title' : 0}).title)
3173  call assert_equal(0, g:Xgetlist({'nr' : 5, 'winid' : 0}).winid)
3174  call assert_equal(0, g:Xgetlist({'nr' : 5, 'changedtick' : 0}).changedtick)
3175  if a:cchar == 'c'
3176    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
3177		\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
3178		\ 'changedtick' : 0}, g:Xgetlist({'nr' : 5, 'all' : 0}))
3179  else
3180    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
3181		\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
3182		\ 'changedtick' : 0, 'filewinid' : 0},
3183		\ g:Xgetlist({'nr' : 5, 'all' : 0}))
3184  endif
3185endfunc
3186
3187func Test_getqflist()
3188  call Xgetlist_empty_tests('c')
3189  call Xgetlist_empty_tests('l')
3190endfunc
3191
3192func Test_getqflist_invalid_nr()
3193  " The following commands used to crash Vim
3194  cexpr ""
3195  call getqflist({'nr' : $XXX_DOES_NOT_EXIST_XXX})
3196
3197  " Cleanup
3198  call setqflist([], 'r')
3199endfunc
3200
3201" Tests for the quickfix/location list changedtick
3202func Xqftick_tests(cchar)
3203  call s:setup_commands(a:cchar)
3204
3205  call g:Xsetlist([], 'f')
3206
3207  Xexpr "F1:10:Line10"
3208  let qfid = g:Xgetlist({'id' : 0}).id
3209  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3210  Xaddexpr "F2:20:Line20\nF2:21:Line21"
3211  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
3212  call g:Xsetlist([], 'a', {'lines' : ["F3:30:Line30", "F3:31:Line31"]})
3213  call assert_equal(3, g:Xgetlist({'changedtick' : 0}).changedtick)
3214  call g:Xsetlist([], 'r', {'lines' : ["F4:40:Line40"]})
3215  call assert_equal(4, g:Xgetlist({'changedtick' : 0}).changedtick)
3216  call g:Xsetlist([], 'a', {'title' : 'New Title'})
3217  call assert_equal(5, g:Xgetlist({'changedtick' : 0}).changedtick)
3218
3219  enew!
3220  call append(0, ["F5:50:L50", "F6:60:L60"])
3221  Xaddbuffer
3222  call assert_equal(6, g:Xgetlist({'changedtick' : 0}).changedtick)
3223  enew!
3224
3225  call g:Xsetlist([], 'a', {'context' : {'bus' : 'pci'}})
3226  call assert_equal(7, g:Xgetlist({'changedtick' : 0}).changedtick)
3227  call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'},
3228	      \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], 'a')
3229  call assert_equal(8, g:Xgetlist({'changedtick' : 0}).changedtick)
3230  call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'},
3231	      \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], ' ')
3232  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3233  call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'},
3234	      \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], 'r')
3235  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
3236
3237  call writefile(["F8:80:L80", "F8:81:L81"], "Xone")
3238  Xfile Xone
3239  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3240  Xaddfile Xone
3241  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
3242
3243  " Test case for updating a non-current quickfix list
3244  call g:Xsetlist([], 'f')
3245  Xexpr "F1:1:L1"
3246  Xexpr "F2:2:L2"
3247  call g:Xsetlist([], 'a', {'nr' : 1, "lines" : ["F10:10:L10"]})
3248  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3249  call assert_equal(2, g:Xgetlist({'nr' : 1, 'changedtick' : 0}).changedtick)
3250
3251  call delete("Xone")
3252endfunc
3253
3254func Test_qf_tick()
3255  call Xqftick_tests('c')
3256  call Xqftick_tests('l')
3257endfunc
3258
3259" Test helpgrep with lang specifier
3260func Xtest_helpgrep_with_lang_specifier(cchar)
3261  call s:setup_commands(a:cchar)
3262  Xhelpgrep Vim@en
3263  call assert_equal('help', &filetype)
3264  call assert_notequal(0, g:Xgetlist({'nr' : '$'}).nr)
3265  new | only
3266endfunc
3267
3268func Test_helpgrep_with_lang_specifier()
3269  call Xtest_helpgrep_with_lang_specifier('c')
3270  call Xtest_helpgrep_with_lang_specifier('l')
3271endfunc
3272
3273" The following test used to crash Vim.
3274" Open the location list window and close the regular window associated with
3275" the location list. When the garbage collection runs now, it incorrectly
3276" marks the location list context as not in use and frees the context.
3277func Test_ll_window_ctx()
3278  call setloclist(0, [], 'f')
3279  call setloclist(0, [], 'a', {'context' : []})
3280  lopen | only
3281  call test_garbagecollect_now()
3282  echo getloclist(0, {'context' : 1}).context
3283  enew | only
3284endfunc
3285
3286" The following test used to crash vim
3287func Test_lfile_crash()
3288  sp Xtest
3289  au QuickFixCmdPre * bw
3290  call assert_fails('lfile', 'E40')
3291  au! QuickFixCmdPre
3292endfunc
3293
3294" The following test used to crash vim
3295func Test_lbuffer_crash()
3296  sv Xtest
3297  augroup QF_Test
3298    au!
3299    au * * bw
3300  augroup END
3301  lbuffer
3302  augroup QF_Test
3303    au!
3304  augroup END
3305endfunc
3306
3307" The following test used to crash vim
3308func Test_lexpr_crash()
3309  augroup QF_Test
3310    au!
3311    au * * call setloclist(0, [], 'f')
3312  augroup END
3313  lexpr ""
3314  augroup QF_Test
3315    au!
3316  augroup END
3317
3318  enew | only
3319  augroup QF_Test
3320    au!
3321    au BufNew * call setloclist(0, [], 'f')
3322  augroup END
3323  lexpr 'x:1:x'
3324  augroup QF_Test
3325    au!
3326  augroup END
3327
3328  enew | only
3329  lexpr ''
3330  lopen
3331  augroup QF_Test
3332    au!
3333    au FileType * call setloclist(0, [], 'f')
3334  augroup END
3335  lexpr ''
3336  augroup QF_Test
3337    au!
3338  augroup END
3339endfunc
3340
3341" The following test used to crash Vim
3342func Test_lvimgrep_crash()
3343  sv Xtest
3344  augroup QF_Test
3345    au!
3346    au * * call setloclist(0, [], 'f')
3347  augroup END
3348  lvimgrep quickfix test_quickfix.vim
3349  augroup QF_Test
3350    au!
3351  augroup END
3352
3353  new | only
3354  augroup QF_Test
3355    au!
3356    au BufEnter * call setloclist(0, [], 'r')
3357  augroup END
3358  call assert_fails('lvimgrep Test_lvimgrep_crash *', 'E926:')
3359  augroup QF_Test
3360    au!
3361  augroup END
3362
3363  enew | only
3364endfunc
3365
3366" Test for the position of the quickfix and location list window
3367func Test_qfwin_pos()
3368  " Open two windows
3369  new | only
3370  new
3371  cexpr ['F1:10:L10']
3372  copen
3373  " Quickfix window should be the bottom most window
3374  call assert_equal(3, winnr())
3375  close
3376  " Open at the very top
3377  wincmd t
3378  topleft copen
3379  call assert_equal(1, winnr())
3380  close
3381  " open left of the current window
3382  wincmd t
3383  below new
3384  leftabove copen
3385  call assert_equal(2, winnr())
3386  close
3387  " open right of the current window
3388  rightbelow copen
3389  call assert_equal(3, winnr())
3390  close
3391endfunc
3392
3393" Tests for quickfix/location lists changed by autocommands when
3394" :vimgrep/:lvimgrep commands are running.
3395func Test_vimgrep_autocmd()
3396  call setqflist([], 'f')
3397  call writefile(['stars'], 'Xtest1.txt')
3398  call writefile(['stars'], 'Xtest2.txt')
3399
3400  " Test 1:
3401  " When searching for a pattern using :vimgrep, if the quickfix list is
3402  " changed by an autocmd, the results should be added to the correct quickfix
3403  " list.
3404  autocmd BufRead Xtest2.txt cexpr '' | cexpr ''
3405  silent vimgrep stars Xtest*.txt
3406  call assert_equal(1, getqflist({'nr' : 0}).nr)
3407  call assert_equal(3, getqflist({'nr' : '$'}).nr)
3408  call assert_equal('Xtest2.txt', bufname(getqflist()[1].bufnr))
3409  au! BufRead Xtest2.txt
3410
3411  " Test 2:
3412  " When searching for a pattern using :vimgrep, if the quickfix list is
3413  " freed, then a error should be given.
3414  silent! %bwipe!
3415  call setqflist([], 'f')
3416  autocmd BufRead Xtest2.txt for i in range(10) | cexpr '' | endfor
3417  call assert_fails('vimgrep stars Xtest*.txt', 'E925:')
3418  au! BufRead Xtest2.txt
3419
3420  " Test 3:
3421  " When searching for a pattern using :lvimgrep, if the location list is
3422  " freed, then the command should error out.
3423  silent! %bwipe!
3424  let g:save_winid = win_getid()
3425  autocmd BufRead Xtest2.txt call setloclist(g:save_winid, [], 'f')
3426  call assert_fails('lvimgrep stars Xtest*.txt', 'E926:')
3427  au! BufRead Xtest2.txt
3428
3429  call delete('Xtest1.txt')
3430  call delete('Xtest2.txt')
3431  call setqflist([], 'f')
3432endfunc
3433
3434" The following test used to crash Vim
3435func Test_lhelpgrep_autocmd()
3436  lhelpgrep quickfix
3437  autocmd QuickFixCmdPost * call setloclist(0, [], 'f')
3438  lhelpgrep buffer
3439  call assert_equal('help', &filetype)
3440  call assert_equal(0, getloclist(0, {'nr' : '$'}).nr)
3441  lhelpgrep tabpage
3442  call assert_equal('help', &filetype)
3443  call assert_equal(1, getloclist(0, {'nr' : '$'}).nr)
3444  au! QuickFixCmdPost
3445
3446  new | only
3447  augroup QF_Test
3448    au!
3449    au BufEnter * call setqflist([], 'f')
3450  augroup END
3451  call assert_fails('helpgrep quickfix', 'E925:')
3452  augroup QF_Test
3453    au! BufEnter
3454  augroup END
3455
3456  new | only
3457  augroup QF_Test
3458    au!
3459    au BufEnter * call setqflist([], 'r')
3460  augroup END
3461  call assert_fails('helpgrep quickfix', 'E925:')
3462  augroup QF_Test
3463    au! BufEnter
3464  augroup END
3465
3466  new | only
3467  augroup QF_Test
3468    au!
3469    au BufEnter * call setloclist(0, [], 'r')
3470  augroup END
3471  call assert_fails('lhelpgrep quickfix', 'E926:')
3472  augroup QF_Test
3473    au! BufEnter
3474  augroup END
3475
3476  new | only
3477endfunc
3478
3479" Test for shortening/simplifying the file name when opening the
3480" quickfix window or when displaying the quickfix list
3481func Test_shorten_fname()
3482  if !has('unix')
3483    return
3484  endif
3485  %bwipe
3486  " Create a quickfix list with a absolute path filename
3487  let fname = getcwd() . '/test_quickfix.vim'
3488  call setqflist([], ' ', {'lines':[fname . ":20:Line20"], 'efm':'%f:%l:%m'})
3489  call assert_equal(fname, bufname('test_quickfix.vim'))
3490  " Opening the quickfix window should simplify the file path
3491  cwindow
3492  call assert_equal('test_quickfix.vim', bufname('test_quickfix.vim'))
3493  cclose
3494  %bwipe
3495  " Create a quickfix list with a absolute path filename
3496  call setqflist([], ' ', {'lines':[fname . ":20:Line20"], 'efm':'%f:%l:%m'})
3497  call assert_equal(fname, bufname('test_quickfix.vim'))
3498  " Displaying the quickfix list should simplify the file path
3499  silent! clist
3500  call assert_equal('test_quickfix.vim', bufname('test_quickfix.vim'))
3501endfunc
3502
3503" Quickfix title tests
3504" In the below tests, 'exe "cmd"' is used to invoke the quickfix commands.
3505" Otherwise due to indentation, the title is set with spaces at the beginning
3506" of the command.
3507func Test_qftitle()
3508  call writefile(["F1:1:Line1"], 'Xerr')
3509
3510  " :cexpr
3511  exe "cexpr readfile('Xerr')"
3512  call assert_equal(":cexpr readfile('Xerr')", getqflist({'title' : 1}).title)
3513
3514  " :cgetexpr
3515  exe "cgetexpr readfile('Xerr')"
3516  call assert_equal(":cgetexpr readfile('Xerr')",
3517					\ getqflist({'title' : 1}).title)
3518
3519  " :caddexpr
3520  call setqflist([], 'f')
3521  exe "caddexpr readfile('Xerr')"
3522  call assert_equal(":caddexpr readfile('Xerr')",
3523					\ getqflist({'title' : 1}).title)
3524
3525  " :cbuffer
3526  new Xerr
3527  exe "cbuffer"
3528  call assert_equal(':cbuffer (Xerr)', getqflist({'title' : 1}).title)
3529
3530  " :cgetbuffer
3531  edit Xerr
3532  exe "cgetbuffer"
3533  call assert_equal(':cgetbuffer (Xerr)', getqflist({'title' : 1}).title)
3534
3535  " :caddbuffer
3536  call setqflist([], 'f')
3537  edit Xerr
3538  exe "caddbuffer"
3539  call assert_equal(':caddbuffer (Xerr)', getqflist({'title' : 1}).title)
3540
3541  " :cfile
3542  exe "cfile Xerr"
3543  call assert_equal(':cfile Xerr', getqflist({'title' : 1}).title)
3544
3545  " :cgetfile
3546  exe "cgetfile Xerr"
3547  call assert_equal(':cgetfile Xerr', getqflist({'title' : 1}).title)
3548
3549  " :caddfile
3550  call setqflist([], 'f')
3551  exe "caddfile Xerr"
3552  call assert_equal(':caddfile Xerr', getqflist({'title' : 1}).title)
3553
3554  " :grep
3555  set grepprg=internal
3556  exe "grep F1 Xerr"
3557  call assert_equal(':grep F1 Xerr', getqflist({'title' : 1}).title)
3558
3559  " :grepadd
3560  call setqflist([], 'f')
3561  exe "grepadd F1 Xerr"
3562  call assert_equal(':grepadd F1 Xerr', getqflist({'title' : 1}).title)
3563  set grepprg&vim
3564
3565  " :vimgrep
3566  exe "vimgrep F1 Xerr"
3567  call assert_equal(':vimgrep F1 Xerr', getqflist({'title' : 1}).title)
3568
3569  " :vimgrepadd
3570  call setqflist([], 'f')
3571  exe "vimgrepadd F1 Xerr"
3572  call assert_equal(':vimgrepadd F1 Xerr', getqflist({'title' : 1}).title)
3573
3574  call setqflist(['F1:10:L10'], ' ')
3575  call assert_equal(':setqflist()', getqflist({'title' : 1}).title)
3576
3577  call setqflist([], 'f')
3578  call setqflist(['F1:10:L10'], 'a')
3579  call assert_equal(':setqflist()', getqflist({'title' : 1}).title)
3580
3581  call setqflist([], 'f')
3582  call setqflist(['F1:10:L10'], 'r')
3583  call assert_equal(':setqflist()', getqflist({'title' : 1}).title)
3584
3585  close
3586  call delete('Xerr')
3587
3588  call setqflist([], ' ', {'title' : 'Errors'})
3589  copen
3590  call assert_equal('Errors', w:quickfix_title)
3591  call setqflist([], 'r', {'items' : [{'filename' : 'a.c', 'lnum' : 10}]})
3592  call assert_equal('Errors', w:quickfix_title)
3593  cclose
3594endfunc
3595
3596func Test_lbuffer_with_bwipe()
3597  new
3598  new
3599  augroup nasty
3600    au * * bwipe
3601  augroup END
3602  lbuffer
3603  augroup nasty
3604    au!
3605  augroup END
3606endfunc
3607
3608" Test for an autocmd freeing the quickfix/location list when cexpr/lexpr is
3609" running
3610func Xexpr_acmd_freelist(cchar)
3611  call s:setup_commands(a:cchar)
3612
3613  " This was using freed memory.
3614  augroup nasty
3615    au * * call g:Xsetlist([], 'f')
3616  augroup END
3617  Xexpr "x"
3618  augroup nasty
3619    au!
3620  augroup END
3621endfunc
3622
3623func Test_cexpr_acmd_freelist()
3624  call Xexpr_acmd_freelist('c')
3625  call Xexpr_acmd_freelist('l')
3626endfunc
3627
3628" Test for commands that create a new quickfix/location list and jump to the
3629" first error automatically.
3630func Xjumpto_first_error_test(cchar)
3631  call s:setup_commands(a:cchar)
3632
3633  call s:create_test_file('Xtestfile1')
3634  call s:create_test_file('Xtestfile2')
3635  let l = ['Xtestfile1:2:Line2', 'Xtestfile2:4:Line4']
3636
3637  " Test for cexpr/lexpr
3638  enew
3639  Xexpr l
3640  call assert_equal('Xtestfile1', bufname(''))
3641  call assert_equal(2, line('.'))
3642
3643  " Test for cfile/lfile
3644  enew
3645  call writefile(l, 'Xerr')
3646  Xfile Xerr
3647  call assert_equal('Xtestfile1', bufname(''))
3648  call assert_equal(2, line('.'))
3649
3650  " Test for cbuffer/lbuffer
3651  edit Xerr
3652  Xbuffer
3653  call assert_equal('Xtestfile1', bufname(''))
3654  call assert_equal(2, line('.'))
3655
3656  call delete('Xerr')
3657  call delete('Xtestfile1')
3658  call delete('Xtestfile2')
3659endfunc
3660
3661func Test_jumpto_first_error()
3662  call Xjumpto_first_error_test('c')
3663  call Xjumpto_first_error_test('l')
3664endfunc
3665
3666" Test for a quickfix autocmd changing the quickfix/location list before
3667" jumping to the first error in the new list.
3668func Xautocmd_changelist(cchar)
3669  call s:setup_commands(a:cchar)
3670
3671  " Test for cfile/lfile
3672  call s:create_test_file('Xtestfile1')
3673  call s:create_test_file('Xtestfile2')
3674  Xexpr 'Xtestfile1:2:Line2'
3675  autocmd QuickFixCmdPost * Xolder
3676  call writefile(['Xtestfile2:4:Line4'], 'Xerr')
3677  Xfile Xerr
3678  call assert_equal('Xtestfile2', bufname(''))
3679  call assert_equal(4, line('.'))
3680  autocmd! QuickFixCmdPost
3681
3682  " Test for cbuffer/lbuffer
3683  call g:Xsetlist([], 'f')
3684  Xexpr 'Xtestfile1:2:Line2'
3685  autocmd QuickFixCmdPost * Xolder
3686  call writefile(['Xtestfile2:4:Line4'], 'Xerr')
3687  edit Xerr
3688  Xbuffer
3689  call assert_equal('Xtestfile2', bufname(''))
3690  call assert_equal(4, line('.'))
3691  autocmd! QuickFixCmdPost
3692
3693  " Test for cexpr/lexpr
3694  call g:Xsetlist([], 'f')
3695  Xexpr 'Xtestfile1:2:Line2'
3696  autocmd QuickFixCmdPost * Xolder
3697  Xexpr 'Xtestfile2:4:Line4'
3698  call assert_equal('Xtestfile2', bufname(''))
3699  call assert_equal(4, line('.'))
3700  autocmd! QuickFixCmdPost
3701
3702  " The grepprg may not be set on non-Unix systems
3703  if has('unix')
3704    " Test for grep/lgrep
3705    call g:Xsetlist([], 'f')
3706    Xexpr 'Xtestfile1:2:Line2'
3707    autocmd QuickFixCmdPost * Xolder
3708    silent Xgrep Line5 Xtestfile2
3709    call assert_equal('Xtestfile2', bufname(''))
3710    call assert_equal(5, line('.'))
3711    autocmd! QuickFixCmdPost
3712  endif
3713
3714  " Test for vimgrep/lvimgrep
3715  call g:Xsetlist([], 'f')
3716  Xexpr 'Xtestfile1:2:Line2'
3717  autocmd QuickFixCmdPost * Xolder
3718  silent Xvimgrep Line5 Xtestfile2
3719  call assert_equal('Xtestfile2', bufname(''))
3720  call assert_equal(5, line('.'))
3721  autocmd! QuickFixCmdPost
3722
3723  " Test for autocommands clearing the quickfix list before jumping to the
3724  " first error. This should not result in an error
3725  autocmd QuickFixCmdPost * call g:Xsetlist([], 'r')
3726  let v:errmsg = ''
3727  " Test for cfile/lfile
3728  Xfile Xerr
3729  call assert_true(v:errmsg !~# 'E42:')
3730  " Test for cbuffer/lbuffer
3731  edit Xerr
3732  Xbuffer
3733  call assert_true(v:errmsg !~# 'E42:')
3734  " Test for cexpr/lexpr
3735  Xexpr 'Xtestfile2:4:Line4'
3736  call assert_true(v:errmsg !~# 'E42:')
3737  " Test for grep/lgrep
3738  " The grepprg may not be set on non-Unix systems
3739  if has('unix')
3740    silent Xgrep Line5 Xtestfile2
3741    call assert_true(v:errmsg !~# 'E42:')
3742  endif
3743  " Test for vimgrep/lvimgrep
3744  call assert_fails('silent Xvimgrep Line5 Xtestfile2', 'E480:')
3745  autocmd! QuickFixCmdPost
3746
3747  call delete('Xerr')
3748  call delete('Xtestfile1')
3749  call delete('Xtestfile2')
3750endfunc
3751
3752func Test_autocmd_changelist()
3753  call Xautocmd_changelist('c')
3754  call Xautocmd_changelist('l')
3755endfunc
3756
3757" Tests for the ':filter /pat/ clist' command
3758func Test_filter_clist()
3759  cexpr ['Xfile1:10:10:Line 10', 'Xfile2:15:15:Line 15']
3760  call assert_equal([' 2 Xfile2:15 col 15: Line 15'],
3761			\ split(execute('filter /Line 15/ clist'), "\n"))
3762  call assert_equal([' 1 Xfile1:10 col 10: Line 10'],
3763			\ split(execute('filter /Xfile1/ clist'), "\n"))
3764  call assert_equal([], split(execute('filter /abc/ clist'), "\n"))
3765
3766  call setqflist([{'module' : 'abc', 'pattern' : 'pat1'},
3767			\ {'module' : 'pqr', 'pattern' : 'pat2'}], ' ')
3768  call assert_equal([' 2 pqr:pat2:  '],
3769			\ split(execute('filter /pqr/ clist'), "\n"))
3770  call assert_equal([' 1 abc:pat1:  '],
3771			\ split(execute('filter /pat1/ clist'), "\n"))
3772endfunc
3773
3774" Tests for the "CTRL-W <CR>" command.
3775func Xview_result_split_tests(cchar)
3776  call s:setup_commands(a:cchar)
3777
3778  " Test that "CTRL-W <CR>" in a qf/ll window fails with empty list.
3779  call g:Xsetlist([])
3780  Xopen
3781  let l:win_count = winnr('$')
3782  call assert_fails('execute "normal! \<C-W>\<CR>"', 'E42')
3783  call assert_equal(l:win_count, winnr('$'))
3784  Xclose
3785endfunc
3786
3787func Test_view_result_split()
3788  call Xview_result_split_tests('c')
3789  call Xview_result_split_tests('l')
3790endfunc
3791
3792" Test that :cc sets curswant
3793func Test_curswant()
3794  helpgrep quickfix
3795  normal! llll
3796  1cc
3797  call assert_equal(getcurpos()[4], virtcol('.'))
3798  cclose | helpclose
3799endfunc
3800
3801" Test for opening a file from the quickfix window using CTRL-W <Enter>
3802" doesn't leave an empty buffer around.
3803func Test_splitview()
3804  call s:create_test_file('Xtestfile1')
3805  call s:create_test_file('Xtestfile2')
3806  new | only
3807  let last_bufnr = bufnr('Test_sv_1', 1)
3808  let l = ['Xtestfile1:2:Line2', 'Xtestfile2:4:Line4']
3809  cgetexpr l
3810  copen
3811  let numbufs = len(getbufinfo())
3812  exe "normal \<C-W>\<CR>"
3813  copen
3814  exe "normal j\<C-W>\<CR>"
3815  " Make sure new empty buffers are not created
3816  call assert_equal(numbufs, len(getbufinfo()))
3817  " Creating a new buffer should use the next available buffer number
3818  call assert_equal(last_bufnr + 4, bufnr("Test_sv_2", 1))
3819  bwipe Test_sv_1
3820  bwipe Test_sv_2
3821  new | only
3822
3823  " When split opening files from location list window, make sure that two
3824  " windows doesn't refer to the same location list
3825  lgetexpr l
3826  let locid = getloclist(0, {'id' : 0}).id
3827  lopen
3828  exe "normal \<C-W>\<CR>"
3829  call assert_notequal(locid, getloclist(0, {'id' : 0}).id)
3830  call assert_equal(0, getloclist(0, {'winid' : 0}).winid)
3831  new | only
3832
3833  " When split opening files from a helpgrep location list window, a new help
3834  " window should be opend with a copy of the location list.
3835  lhelpgrep window
3836  let locid = getloclist(0, {'id' : 0}).id
3837  lwindow
3838  exe "normal j\<C-W>\<CR>"
3839  call assert_notequal(locid, getloclist(0, {'id' : 0}).id)
3840  call assert_equal(0, getloclist(0, {'winid' : 0}).winid)
3841  new | only
3842
3843  call delete('Xtestfile1')
3844  call delete('Xtestfile2')
3845endfunc
3846
3847" Test for parsing entries using visual screen column
3848func Test_viscol()
3849  enew
3850  call writefile(["Col1\tCol2\tCol3"], 'Xfile1')
3851  edit Xfile1
3852
3853  " Use byte offset for column number
3854  set efm&
3855  cexpr "Xfile1:1:5:XX\nXfile1:1:9:YY\nXfile1:1:20:ZZ"
3856  call assert_equal([5, 8], [col('.'), virtcol('.')])
3857  cnext
3858  call assert_equal([9, 12], [col('.'), virtcol('.')])
3859  cnext
3860  call assert_equal([14, 20], [col('.'), virtcol('.')])
3861
3862  " Use screen column offset for column number
3863  set efm=%f:%l:%v:%m
3864  cexpr "Xfile1:1:8:XX\nXfile1:1:12:YY\nXfile1:1:20:ZZ"
3865  call assert_equal([5, 8], [col('.'), virtcol('.')])
3866  cnext
3867  call assert_equal([9, 12], [col('.'), virtcol('.')])
3868  cnext
3869  call assert_equal([14, 20], [col('.'), virtcol('.')])
3870  cexpr "Xfile1:1:6:XX\nXfile1:1:15:YY\nXfile1:1:24:ZZ"
3871  call assert_equal([5, 8], [col('.'), virtcol('.')])
3872  cnext
3873  call assert_equal([10, 16], [col('.'), virtcol('.')])
3874  cnext
3875  call assert_equal([14, 20], [col('.'), virtcol('.')])
3876
3877  enew
3878  call writefile(["Col1\täü\töß\tCol4"], 'Xfile1')
3879
3880  " Use byte offset for column number
3881  set efm&
3882  cexpr "Xfile1:1:8:XX\nXfile1:1:11:YY\nXfile1:1:16:ZZ"
3883  call assert_equal([8, 10], [col('.'), virtcol('.')])
3884  cnext
3885  call assert_equal([11, 17], [col('.'), virtcol('.')])
3886  cnext
3887  call assert_equal([16, 25], [col('.'), virtcol('.')])
3888
3889  " Use screen column offset for column number
3890  set efm=%f:%l:%v:%m
3891  cexpr "Xfile1:1:10:XX\nXfile1:1:17:YY\nXfile1:1:25:ZZ"
3892  call assert_equal([8, 10], [col('.'), virtcol('.')])
3893  cnext
3894  call assert_equal([11, 17], [col('.'), virtcol('.')])
3895  cnext
3896  call assert_equal([16, 25], [col('.'), virtcol('.')])
3897
3898  enew | only
3899  set efm&
3900  call delete('Xfile1')
3901endfunc
3902