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])
1814endfunc
1815
1816func Test_history()
1817  call HistoryTest('c')
1818  call HistoryTest('l')
1819endfunc
1820
1821func Test_duplicate_buf()
1822  " make sure we can get the highest buffer number
1823  edit DoesNotExist
1824  edit DoesNotExist2
1825  let last_buffer = bufnr("$")
1826
1827  " make sure only one buffer is created
1828  call writefile(['this one', 'that one'], 'Xgrepthis')
1829  vimgrep one Xgrepthis
1830  vimgrep one Xgrepthis
1831  call assert_equal(last_buffer + 1, bufnr("$"))
1832
1833  call delete('Xgrepthis')
1834endfunc
1835
1836" Quickfix/Location list set/get properties tests
1837func Xproperty_tests(cchar)
1838    call s:setup_commands(a:cchar)
1839
1840    " Error cases
1841    call assert_fails('call g:Xgetlist(99)', 'E715:')
1842    call assert_fails('call g:Xsetlist(99)', 'E714:')
1843    call assert_fails('call g:Xsetlist([], "a", [])', 'E715:')
1844
1845    " Set and get the title
1846    call g:Xsetlist([])
1847    Xopen
1848    wincmd p
1849    call g:Xsetlist([{'filename':'foo', 'lnum':27}])
1850    let s = g:Xsetlist([], 'a', {'title' : 'Sample'})
1851    call assert_equal(0, s)
1852    let d = g:Xgetlist({"title":1})
1853    call assert_equal('Sample', d.title)
1854    " Try setting title to a non-string value
1855    call assert_equal(-1, g:Xsetlist([], 'a', {'title' : ['Test']}))
1856    call assert_equal('Sample', g:Xgetlist({"title":1}).title)
1857
1858    Xopen
1859    call assert_equal('Sample', w:quickfix_title)
1860    Xclose
1861
1862    " Tests for action argument
1863    silent! Xolder 999
1864    let qfnr = g:Xgetlist({'all':1}).nr
1865    call g:Xsetlist([], 'r', {'title' : 'N1'})
1866    call assert_equal('N1', g:Xgetlist({'all':1}).title)
1867    call g:Xsetlist([], ' ', {'title' : 'N2'})
1868    call assert_equal(qfnr + 1, g:Xgetlist({'all':1}).nr)
1869
1870    let res = g:Xgetlist({'nr': 0})
1871    call assert_equal(qfnr + 1, res.nr)
1872    call assert_equal(['nr'], keys(res))
1873
1874    call g:Xsetlist([], ' ', {'title' : 'N3'})
1875    call assert_equal('N2', g:Xgetlist({'nr':2, 'title':1}).title)
1876
1877    " Changing the title of an earlier quickfix list
1878    call g:Xsetlist([], 'r', {'title' : 'NewTitle', 'nr' : 2})
1879    call assert_equal('NewTitle', g:Xgetlist({'nr':2, 'title':1}).title)
1880
1881    " Changing the title of an invalid quickfix list
1882    call assert_equal(-1, g:Xsetlist([], ' ',
1883		\ {'title' : 'SomeTitle', 'nr' : 99}))
1884    call assert_equal(-1, g:Xsetlist([], ' ',
1885		\ {'title' : 'SomeTitle', 'nr' : 'abc'}))
1886
1887    if a:cchar == 'c'
1888	copen
1889	call assert_equal({'winid':win_getid()}, getqflist({'winid':1}))
1890	cclose
1891    endif
1892
1893    " Invalid arguments
1894    call assert_fails('call g:Xgetlist([])', 'E715')
1895    call assert_fails('call g:Xsetlist([], "a", [])', 'E715')
1896    let s = g:Xsetlist([], 'a', {'abc':1})
1897    call assert_equal(-1, s)
1898
1899    call assert_equal({}, g:Xgetlist({'abc':1}))
1900    call assert_equal('', g:Xgetlist({'nr':99, 'title':1}).title)
1901    call assert_equal('', g:Xgetlist({'nr':[], 'title':1}).title)
1902
1903    if a:cchar == 'l'
1904	call assert_equal({}, getloclist(99, {'title': 1}))
1905    endif
1906
1907    " Context related tests
1908    let s = g:Xsetlist([], 'a', {'context':[1,2,3]})
1909    call assert_equal(0, s)
1910    call test_garbagecollect_now()
1911    let d = g:Xgetlist({'context':1})
1912    call assert_equal([1,2,3], d.context)
1913    call g:Xsetlist([], 'a', {'context':{'color':'green'}})
1914    let d = g:Xgetlist({'context':1})
1915    call assert_equal({'color':'green'}, d.context)
1916    call g:Xsetlist([], 'a', {'context':"Context info"})
1917    let d = g:Xgetlist({'context':1})
1918    call assert_equal("Context info", d.context)
1919    call g:Xsetlist([], 'a', {'context':246})
1920    let d = g:Xgetlist({'context':1})
1921    call assert_equal(246, d.context)
1922    if a:cchar == 'l'
1923	" Test for copying context across two different location lists
1924	new | only
1925	let w1_id = win_getid()
1926	let l = [1]
1927	call setloclist(0, [], 'a', {'context':l})
1928	new
1929	let w2_id = win_getid()
1930	call add(l, 2)
1931	call assert_equal([1, 2], getloclist(w1_id, {'context':1}).context)
1932	call assert_equal([1, 2], getloclist(w2_id, {'context':1}).context)
1933	unlet! l
1934	call assert_equal([1, 2], getloclist(w2_id, {'context':1}).context)
1935	only
1936	call setloclist(0, [], 'f')
1937	call assert_equal('', getloclist(0, {'context':1}).context)
1938    endif
1939
1940    " Test for changing the context of previous quickfix lists
1941    call g:Xsetlist([], 'f')
1942    Xexpr "One"
1943    Xexpr "Two"
1944    Xexpr "Three"
1945    call g:Xsetlist([], 'r', {'context' : [1], 'nr' : 1})
1946    call g:Xsetlist([], 'a', {'context' : [2], 'nr' : 2})
1947    " Also, check for setting the context using quickfix list number zero.
1948    call g:Xsetlist([], 'r', {'context' : [3], 'nr' : 0})
1949    call test_garbagecollect_now()
1950    let l = g:Xgetlist({'nr' : 1, 'context' : 1})
1951    call assert_equal([1], l.context)
1952    let l = g:Xgetlist({'nr' : 2, 'context' : 1})
1953    call assert_equal([2], l.context)
1954    let l = g:Xgetlist({'nr' : 3, 'context' : 1})
1955    call assert_equal([3], l.context)
1956
1957    " Test for changing the context through reference and for garbage
1958    " collection of quickfix context
1959    let l = ["red"]
1960    call g:Xsetlist([], ' ', {'context' : l})
1961    call add(l, "blue")
1962    let x = g:Xgetlist({'context' : 1})
1963    call add(x.context, "green")
1964    call assert_equal(["red", "blue", "green"], l)
1965    call assert_equal(["red", "blue", "green"], x.context)
1966    unlet l
1967    call test_garbagecollect_now()
1968    let m = g:Xgetlist({'context' : 1})
1969    call assert_equal(["red", "blue", "green"], m.context)
1970
1971    " Test for setting/getting items
1972    Xexpr ""
1973    let qfprev = g:Xgetlist({'nr':0})
1974    let s = g:Xsetlist([], ' ', {'title':'Green',
1975		\ 'items' : [{'filename':'F1', 'lnum':10}]})
1976    call assert_equal(0, s)
1977    let qfcur = g:Xgetlist({'nr':0})
1978    call assert_true(qfcur.nr == qfprev.nr + 1)
1979    let l = g:Xgetlist({'items':1})
1980    call assert_equal('F1', bufname(l.items[0].bufnr))
1981    call assert_equal(10, l.items[0].lnum)
1982    call g:Xsetlist([], 'a', {'items' : [{'filename':'F2', 'lnum':20},
1983		\  {'filename':'F2', 'lnum':30}]})
1984    let l = g:Xgetlist({'items':1})
1985    call assert_equal('F2', bufname(l.items[2].bufnr))
1986    call assert_equal(30, l.items[2].lnum)
1987    call g:Xsetlist([], 'r', {'items' : [{'filename':'F3', 'lnum':40}]})
1988    let l = g:Xgetlist({'items':1})
1989    call assert_equal('F3', bufname(l.items[0].bufnr))
1990    call assert_equal(40, l.items[0].lnum)
1991    call g:Xsetlist([], 'r', {'items' : []})
1992    let l = g:Xgetlist({'items':1})
1993    call assert_equal(0, len(l.items))
1994
1995    call g:Xsetlist([], 'r', {'title' : 'TestTitle'})
1996    call g:Xsetlist([], 'r', {'items' : [{'filename' : 'F1', 'lnum' : 10, 'text' : 'L10'}]})
1997    call g:Xsetlist([], 'r', {'items' : [{'filename' : 'F1', 'lnum' : 10, 'text' : 'L10'}]})
1998    call assert_equal('TestTitle', g:Xgetlist({'title' : 1}).title)
1999
2000    " Test for getting id of window associated with a location list window
2001    if a:cchar == 'l'
2002      only
2003      call assert_equal(0, g:Xgetlist({'all' : 1}).filewinid)
2004      let wid = win_getid()
2005      Xopen
2006      call assert_equal(wid, g:Xgetlist({'filewinid' : 1}).filewinid)
2007      wincmd w
2008      call assert_equal(0, g:Xgetlist({'filewinid' : 1}).filewinid)
2009      only
2010    endif
2011
2012    " The following used to crash Vim with address sanitizer
2013    call g:Xsetlist([], 'f')
2014    call g:Xsetlist([], 'a', {'items' : [{'filename':'F1', 'lnum':10}]})
2015    call assert_equal(10, g:Xgetlist({'items':1}).items[0].lnum)
2016
2017    " Try setting the items using a string
2018    call assert_equal(-1, g:Xsetlist([], ' ', {'items' : 'Test'}))
2019
2020    " Save and restore the quickfix stack
2021    call g:Xsetlist([], 'f')
2022    call assert_equal(0, g:Xgetlist({'nr':'$'}).nr)
2023    Xexpr "File1:10:Line1"
2024    Xexpr "File2:20:Line2"
2025    Xexpr "File3:30:Line3"
2026    let last_qf = g:Xgetlist({'nr':'$'}).nr
2027    call assert_equal(3, last_qf)
2028    let qstack = []
2029    for i in range(1, last_qf)
2030	let qstack = add(qstack, g:Xgetlist({'nr':i, 'all':1}))
2031    endfor
2032    call g:Xsetlist([], 'f')
2033    for i in range(len(qstack))
2034	call g:Xsetlist([], ' ', qstack[i])
2035    endfor
2036    call assert_equal(3, g:Xgetlist({'nr':'$'}).nr)
2037    call assert_equal(10, g:Xgetlist({'nr':1, 'items':1}).items[0].lnum)
2038    call assert_equal(20, g:Xgetlist({'nr':2, 'items':1}).items[0].lnum)
2039    call assert_equal(30, g:Xgetlist({'nr':3, 'items':1}).items[0].lnum)
2040    call g:Xsetlist([], 'f')
2041
2042    " Swap two quickfix lists
2043    Xexpr "File1:10:Line10"
2044    Xexpr "File2:20:Line20"
2045    Xexpr "File3:30:Line30"
2046    call g:Xsetlist([], 'r', {'nr':1,'title':'Colors','context':['Colors']})
2047    call g:Xsetlist([], 'r', {'nr':2,'title':'Fruits','context':['Fruits']})
2048    let l1=g:Xgetlist({'nr':1,'all':1})
2049    let l2=g:Xgetlist({'nr':2,'all':1})
2050    let save_id = l1.id
2051    let l1.id=l2.id
2052    let l2.id=save_id
2053    call g:Xsetlist([], 'r', l1)
2054    call g:Xsetlist([], 'r', l2)
2055    let newl1=g:Xgetlist({'nr':1,'all':1})
2056    let newl2=g:Xgetlist({'nr':2,'all':1})
2057    call assert_equal('Fruits', newl1.title)
2058    call assert_equal(['Fruits'], newl1.context)
2059    call assert_equal('Line20', newl1.items[0].text)
2060    call assert_equal('Colors', newl2.title)
2061    call assert_equal(['Colors'], newl2.context)
2062    call assert_equal('Line10', newl2.items[0].text)
2063    call g:Xsetlist([], 'f')
2064endfunc
2065
2066func Test_qf_property()
2067    call Xproperty_tests('c')
2068    call Xproperty_tests('l')
2069endfunc
2070
2071" Tests for the QuickFixCmdPre/QuickFixCmdPost autocommands
2072func QfAutoCmdHandler(loc, cmd)
2073  call add(g:acmds, a:loc . a:cmd)
2074endfunc
2075
2076func Test_Autocmd()
2077  autocmd QuickFixCmdPre * call QfAutoCmdHandler('pre', expand('<amatch>'))
2078  autocmd QuickFixCmdPost * call QfAutoCmdHandler('post', expand('<amatch>'))
2079
2080  let g:acmds = []
2081  cexpr "F1:10:Line 10"
2082  caddexpr "F1:20:Line 20"
2083  cgetexpr "F1:30:Line 30"
2084  cexpr ""
2085  caddexpr ""
2086  cgetexpr ""
2087  silent! cexpr non_existing_func()
2088  silent! caddexpr non_existing_func()
2089  silent! cgetexpr non_existing_func()
2090  let l = ['precexpr',
2091	      \ 'postcexpr',
2092	      \ 'precaddexpr',
2093	      \ 'postcaddexpr',
2094	      \ 'precgetexpr',
2095	      \ 'postcgetexpr',
2096	      \ 'precexpr',
2097	      \ 'postcexpr',
2098	      \ 'precaddexpr',
2099	      \ 'postcaddexpr',
2100	      \ 'precgetexpr',
2101	      \ 'postcgetexpr',
2102	      \ 'precexpr',
2103	      \ 'precaddexpr',
2104	      \ 'precgetexpr']
2105  call assert_equal(l, g:acmds)
2106
2107  let g:acmds = []
2108  enew! | call append(0, "F2:10:Line 10")
2109  cbuffer!
2110  enew! | call append(0, "F2:20:Line 20")
2111  cgetbuffer
2112  enew! | call append(0, "F2:30:Line 30")
2113  caddbuffer
2114  new
2115  let bnum = bufnr('%')
2116  bunload
2117  exe 'silent! cbuffer! ' . bnum
2118  exe 'silent! cgetbuffer ' . bnum
2119  exe 'silent! caddbuffer ' . bnum
2120  enew!
2121  let l = ['precbuffer',
2122	      \ 'postcbuffer',
2123	      \ 'precgetbuffer',
2124	      \ 'postcgetbuffer',
2125	      \ 'precaddbuffer',
2126	      \ 'postcaddbuffer',
2127	      \ 'precbuffer',
2128	      \ 'precgetbuffer',
2129	      \ 'precaddbuffer']
2130  call assert_equal(l, g:acmds)
2131
2132  call writefile(['Xtest:1:Line1'], 'Xtest')
2133  call writefile([], 'Xempty')
2134  let g:acmds = []
2135  cfile Xtest
2136  caddfile Xtest
2137  cgetfile Xtest
2138  cfile Xempty
2139  caddfile Xempty
2140  cgetfile Xempty
2141  silent! cfile do_not_exist
2142  silent! caddfile do_not_exist
2143  silent! cgetfile do_not_exist
2144  let l = ['precfile',
2145	      \ 'postcfile',
2146	      \ 'precaddfile',
2147	      \ 'postcaddfile',
2148	      \ 'precgetfile',
2149	      \ 'postcgetfile',
2150	      \ 'precfile',
2151	      \ 'postcfile',
2152	      \ 'precaddfile',
2153	      \ 'postcaddfile',
2154	      \ 'precgetfile',
2155	      \ 'postcgetfile',
2156	      \ 'precfile',
2157	      \ 'postcfile',
2158	      \ 'precaddfile',
2159	      \ 'postcaddfile',
2160	      \ 'precgetfile',
2161	      \ 'postcgetfile']
2162  call assert_equal(l, g:acmds)
2163
2164  let g:acmds = []
2165  helpgrep quickfix
2166  silent! helpgrep non_existing_help_topic
2167  vimgrep test Xtest
2168  vimgrepadd test Xtest
2169  silent! vimgrep non_existing_test Xtest
2170  silent! vimgrepadd non_existing_test Xtest
2171  set makeprg=
2172  silent! make
2173  set makeprg&
2174  let l = ['prehelpgrep',
2175	      \ 'posthelpgrep',
2176	      \ 'prehelpgrep',
2177	      \ 'posthelpgrep',
2178	      \ 'previmgrep',
2179	      \ 'postvimgrep',
2180	      \ 'previmgrepadd',
2181	      \ 'postvimgrepadd',
2182	      \ 'previmgrep',
2183	      \ 'postvimgrep',
2184	      \ 'previmgrepadd',
2185	      \ 'postvimgrepadd',
2186	      \ 'premake',
2187	      \ 'postmake']
2188  call assert_equal(l, g:acmds)
2189
2190  if has('unix')
2191    " Run this test only on Unix-like systems. The grepprg may not be set on
2192    " non-Unix systems.
2193    " The following lines are used for the grep test. Don't remove.
2194    " Grep_Autocmd_Text: Match 1
2195    " GrepAdd_Autocmd_Text: Match 2
2196    let g:acmds = []
2197    silent grep Grep_Autocmd_Text test_quickfix.vim
2198    silent grepadd GrepAdd_Autocmd_Text test_quickfix.vim
2199    silent grep abc123def Xtest
2200    silent grepadd abc123def Xtest
2201    let l = ['pregrep',
2202		\ 'postgrep',
2203		\ 'pregrepadd',
2204		\ 'postgrepadd',
2205		\ 'pregrep',
2206		\ 'postgrep',
2207		\ 'pregrepadd',
2208		\ 'postgrepadd']
2209    call assert_equal(l, g:acmds)
2210  endif
2211
2212  call delete('Xtest')
2213  call delete('Xempty')
2214  au! QuickFixCmdPre
2215  au! QuickFixCmdPost
2216endfunc
2217
2218func Test_Autocmd_Exception()
2219  set efm=%m
2220  lgetexpr '?'
2221
2222  try
2223    call DoesNotExit()
2224  catch
2225    lgetexpr '1'
2226  finally
2227    lgetexpr '1'
2228  endtry
2229
2230  call assert_equal('1', getloclist(0)[0].text)
2231
2232  set efm&vim
2233endfunc
2234
2235func Test_caddbuffer_wrong()
2236  " This used to cause a memory access in freed memory.
2237  let save_efm = &efm
2238  set efm=%EEEE%m,%WWWW,%+CCCC%>%#,%GGGG%.#
2239  cgetexpr ['WWWW', 'EEEE', 'CCCC']
2240  let &efm = save_efm
2241  caddbuffer
2242  bwipe!
2243endfunc
2244
2245func Test_caddexpr_wrong()
2246  " This used to cause a memory access in freed memory.
2247  cbuffer
2248  cbuffer
2249  copen
2250  let save_efm = &efm
2251  set efm=%
2252  call assert_fails('caddexpr ""', 'E376:')
2253  let &efm = save_efm
2254endfunc
2255
2256func Test_dirstack_cleanup()
2257  " This used to cause a memory access in freed memory.
2258  let save_efm = &efm
2259  lexpr '0'
2260  lopen
2261  fun X(c)
2262    let save_efm=&efm
2263    set efm=%D%f
2264    if a:c == 'c'
2265      caddexpr '::'
2266    else
2267      laddexpr ':0:0'
2268    endif
2269    let &efm=save_efm
2270  endfun
2271  call X('c')
2272  call X('l')
2273  call setqflist([], 'r')
2274  caddbuffer
2275  let &efm = save_efm
2276endfunc
2277
2278" Tests for jumping to entries from the location list window and quickfix
2279" window
2280func Test_cwindow_jump()
2281  set efm=%f%%%l%%%m
2282  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2283  lopen | only
2284  lfirst
2285  call assert_true(winnr('$') == 2)
2286  call assert_true(winnr() == 1)
2287  " Location list for the new window should be set
2288  call assert_true(getloclist(0)[2].text == 'Line 30')
2289
2290  " Open a scratch buffer
2291  " Open a new window and create a location list
2292  " Open the location list window and close the other window
2293  " Jump to an entry.
2294  " Should create a new window and jump to the entry. The scrtach buffer
2295  " should not be used.
2296  enew | only
2297  set buftype=nofile
2298  below new
2299  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2300  lopen
2301  2wincmd c
2302  lnext
2303  call assert_true(winnr('$') == 3)
2304  call assert_true(winnr() == 2)
2305
2306  " Open two windows with two different location lists
2307  " Open the location list window and close the previous window
2308  " Jump to an entry in the location list window
2309  " Should open the file in the first window and not set the location list.
2310  enew | only
2311  lgetexpr ["F1%5%Line 5"]
2312  below new
2313  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2314  lopen
2315  2wincmd c
2316  lnext
2317  call assert_true(winnr() == 1)
2318  call assert_true(getloclist(0)[0].text == 'Line 5')
2319
2320  enew | only
2321  cgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2322  copen
2323  cnext
2324  call assert_true(winnr('$') == 2)
2325  call assert_true(winnr() == 1)
2326
2327  enew | only
2328  set efm&vim
2329endfunc
2330
2331func XvimgrepTests(cchar)
2332  call s:setup_commands(a:cchar)
2333
2334  call writefile(['Editor:VIM vim',
2335	      \ 'Editor:Emacs EmAcS',
2336	      \ 'Editor:Notepad NOTEPAD'], 'Xtestfile1')
2337  call writefile(['Linux', 'MacOS', 'MS-Windows'], 'Xtestfile2')
2338
2339  " Error cases
2340  call assert_fails('Xvimgrep /abc *', 'E682:')
2341
2342  let @/=''
2343  call assert_fails('Xvimgrep // *', 'E35:')
2344
2345  call assert_fails('Xvimgrep abc', 'E683:')
2346  call assert_fails('Xvimgrep a1b2c3 Xtestfile1', 'E480:')
2347  call assert_fails('Xvimgrep pat Xa1b2c3', 'E480:')
2348
2349  Xexpr ""
2350  Xvimgrepadd Notepad Xtestfile1
2351  Xvimgrepadd MacOS Xtestfile2
2352  let l = g:Xgetlist()
2353  call assert_equal(2, len(l))
2354  call assert_equal('Editor:Notepad NOTEPAD', l[0].text)
2355
2356  Xvimgrep #\cvim#g Xtestfile?
2357  let l = g:Xgetlist()
2358  call assert_equal(2, len(l))
2359  call assert_equal(8, l[0].col)
2360  call assert_equal(12, l[1].col)
2361
2362  1Xvimgrep ?Editor? Xtestfile*
2363  let l = g:Xgetlist()
2364  call assert_equal(1, len(l))
2365  call assert_equal('Editor:VIM vim', l[0].text)
2366
2367  edit +3 Xtestfile2
2368  Xvimgrep +\cemacs+j Xtestfile1
2369  let l = g:Xgetlist()
2370  call assert_equal('Xtestfile2', bufname(''))
2371  call assert_equal('Editor:Emacs EmAcS', l[0].text)
2372
2373  " Test for unloading a buffer after vimgrep searched the buffer
2374  %bwipe
2375  Xvimgrep /Editor/j Xtestfile*
2376  call assert_equal(0, getbufinfo('Xtestfile1')[0].loaded)
2377  call assert_equal([], getbufinfo('Xtestfile2'))
2378
2379  call delete('Xtestfile1')
2380  call delete('Xtestfile2')
2381endfunc
2382
2383" Tests for the :vimgrep command
2384func Test_vimgrep()
2385  call XvimgrepTests('c')
2386  call XvimgrepTests('l')
2387endfunc
2388
2389" Test for incsearch highlighting of the :vimgrep pattern
2390" This test used to cause "E315: ml_get: invalid lnum" errors.
2391func Test_vimgrep_incsearch()
2392  enew
2393  set incsearch
2394  call test_override("char_avail", 1)
2395
2396  call feedkeys(":2vimgrep assert test_quickfix.vim test_cdo.vim\<CR>", "ntx")
2397  let l = getqflist()
2398  call assert_equal(2, len(l))
2399
2400  call test_override("ALL", 0)
2401  set noincsearch
2402endfunc
2403
2404func XfreeTests(cchar)
2405  call s:setup_commands(a:cchar)
2406
2407  enew | only
2408
2409  " Deleting the quickfix stack should work even When the current list is
2410  " somewhere in the middle of the stack
2411  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2412  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2413  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2414  Xolder
2415  call g:Xsetlist([], 'f')
2416  call assert_equal(0, len(g:Xgetlist()))
2417
2418  " After deleting the stack, adding a new list should create a stack with a
2419  " single list.
2420  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2421  call assert_equal(1, g:Xgetlist({'all':1}).nr)
2422
2423  " Deleting the stack from a quickfix window should update/clear the
2424  " quickfix/location list window.
2425  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2426  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2427  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2428  Xolder
2429  Xwindow
2430  call g:Xsetlist([], 'f')
2431  call assert_equal(2, winnr('$'))
2432  call assert_equal(1, line('$'))
2433  Xclose
2434
2435  " Deleting the stack from a non-quickfix window should update/clear the
2436  " quickfix/location list window.
2437  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2438  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2439  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2440  Xolder
2441  Xwindow
2442  wincmd p
2443  call g:Xsetlist([], 'f')
2444  call assert_equal(0, len(g:Xgetlist()))
2445  wincmd p
2446  call assert_equal(2, winnr('$'))
2447  call assert_equal(1, line('$'))
2448
2449  " After deleting the location list stack, if the location list window is
2450  " opened, then a new location list should be created. So opening the
2451  " location list window again should not create a new window.
2452  if a:cchar == 'l'
2453      lexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2454      wincmd p
2455      lopen
2456      call assert_equal(2, winnr('$'))
2457  endif
2458  Xclose
2459endfunc
2460
2461" Tests for the quickfix free functionality
2462func Test_qf_free()
2463  call XfreeTests('c')
2464  call XfreeTests('l')
2465endfunc
2466
2467" Test for buffer overflow when parsing lines and adding new entries to
2468" the quickfix list.
2469func Test_bufoverflow()
2470  set efm=%f:%l:%m
2471  cgetexpr ['File1:100:' . repeat('x', 1025)]
2472
2473  set efm=%+GCompiler:\ %.%#,%f:%l:%m
2474  cgetexpr ['Compiler: ' . repeat('a', 1015), 'File1:10:Hello World']
2475
2476  set efm=%DEntering\ directory\ %f,%f:%l:%m
2477  cgetexpr ['Entering directory ' . repeat('a', 1006),
2478	      \ 'File1:10:Hello World']
2479  set efm&vim
2480endfunc
2481
2482" Tests for getting the quickfix stack size
2483func XsizeTests(cchar)
2484  call s:setup_commands(a:cchar)
2485
2486  call g:Xsetlist([], 'f')
2487  call assert_equal(0, g:Xgetlist({'nr':'$'}).nr)
2488  call assert_equal('', g:Xgetlist({'nr':'$', 'all':1}).title)
2489  call assert_equal(0, g:Xgetlist({'nr':0}).nr)
2490
2491  Xexpr "File1:10:Line1"
2492  Xexpr "File2:20:Line2"
2493  Xexpr "File3:30:Line3"
2494  Xolder | Xolder
2495  call assert_equal(3, g:Xgetlist({'nr':'$'}).nr)
2496  call g:Xsetlist([], 'f')
2497
2498  Xexpr "File1:10:Line1"
2499  Xexpr "File2:20:Line2"
2500  Xexpr "File3:30:Line3"
2501  Xolder | Xolder
2502  call g:Xsetlist([], 'a', {'nr':'$', 'title':'Compiler'})
2503  call assert_equal('Compiler', g:Xgetlist({'nr':3, 'all':1}).title)
2504endfunc
2505
2506func Test_Qf_Size()
2507  call XsizeTests('c')
2508  call XsizeTests('l')
2509endfunc
2510
2511func Test_cclose_from_copen()
2512    augroup QF_Test
2513	au!
2514        au FileType qf :call assert_fails(':cclose', 'E788')
2515    augroup END
2516    copen
2517    augroup QF_Test
2518	au!
2519    augroup END
2520    augroup! QF_Test
2521endfunc
2522
2523func Test_cclose_in_autocmd()
2524  " Problem is only triggered if "starting" is zero, so that the OptionsSet
2525  " event will be triggered.
2526  call test_override('starting', 1)
2527  augroup QF_Test
2528    au!
2529    au FileType qf :call assert_fails(':cclose', 'E788')
2530  augroup END
2531  copen
2532  augroup QF_Test
2533    au!
2534  augroup END
2535  augroup! QF_Test
2536  call test_override('starting', 0)
2537endfunc
2538
2539" Check that ":file" without an argument is possible even when "curbuf_lock"
2540" is set.
2541func Test_file_from_copen()
2542  " Works without argument.
2543  augroup QF_Test
2544    au!
2545    au FileType qf file
2546  augroup END
2547  copen
2548
2549  augroup QF_Test
2550    au!
2551  augroup END
2552  cclose
2553
2554  " Fails with argument.
2555  augroup QF_Test
2556    au!
2557    au FileType qf call assert_fails(':file foo', 'E788')
2558  augroup END
2559  copen
2560  augroup QF_Test
2561    au!
2562  augroup END
2563  cclose
2564
2565  augroup! QF_Test
2566endfunction
2567
2568func Test_resize_from_copen()
2569    augroup QF_Test
2570	au!
2571        au FileType qf resize 5
2572    augroup END
2573    try
2574	" This should succeed without any exception.  No other buffers are
2575	" involved in the autocmd.
2576	copen
2577    finally
2578	augroup QF_Test
2579	    au!
2580	augroup END
2581	augroup! QF_Test
2582    endtry
2583endfunc
2584
2585" Tests for the quickfix buffer b:changedtick variable
2586func Xchangedtick_tests(cchar)
2587  call s:setup_commands(a:cchar)
2588
2589  new | only
2590
2591  Xexpr "" | Xexpr "" | Xexpr ""
2592
2593  Xopen
2594  Xolder
2595  Xolder
2596  Xaddexpr "F1:10:Line10"
2597  Xaddexpr "F2:20:Line20"
2598  call g:Xsetlist([{"filename":"F3", "lnum":30, "text":"Line30"}], 'a')
2599  call g:Xsetlist([], 'f')
2600  call assert_equal(8, getbufvar('%', 'changedtick'))
2601  Xclose
2602endfunc
2603
2604func Test_changedtick()
2605  call Xchangedtick_tests('c')
2606  call Xchangedtick_tests('l')
2607endfunc
2608
2609" Tests for parsing an expression using setqflist()
2610func Xsetexpr_tests(cchar)
2611  call s:setup_commands(a:cchar)
2612
2613  let t = ["File1:10:Line10", "File1:20:Line20"]
2614  call g:Xsetlist([], ' ', {'lines' : t})
2615  call g:Xsetlist([], 'a', {'lines' : ["File1:30:Line30"]})
2616
2617  let l = g:Xgetlist()
2618  call assert_equal(3, len(l))
2619  call assert_equal(20, l[1].lnum)
2620  call assert_equal('Line30', l[2].text)
2621  call g:Xsetlist([], 'r', {'lines' : ["File2:5:Line5"]})
2622  let l = g:Xgetlist()
2623  call assert_equal(1, len(l))
2624  call assert_equal('Line5', l[0].text)
2625  call assert_equal(-1, g:Xsetlist([], 'a', {'lines' : 10}))
2626  call assert_equal(-1, g:Xsetlist([], 'a', {'lines' : "F1:10:L10"}))
2627
2628  call g:Xsetlist([], 'f')
2629  " Add entries to multiple lists
2630  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["File1:10:Line10"]})
2631  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["File2:20:Line20"]})
2632  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["File1:15:Line15"]})
2633  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["File2:25:Line25"]})
2634  call assert_equal('Line15', g:Xgetlist({'nr':1, 'items':1}).items[1].text)
2635  call assert_equal('Line25', g:Xgetlist({'nr':2, 'items':1}).items[1].text)
2636
2637  " Adding entries using a custom efm
2638  set efm&
2639  call g:Xsetlist([], ' ', {'efm' : '%f#%l#%m',
2640				\ 'lines' : ["F1#10#L10", "F2#20#L20"]})
2641  call assert_equal(20, g:Xgetlist({'items':1}).items[1].lnum)
2642  call g:Xsetlist([], 'a', {'efm' : '%f#%l#%m', 'lines' : ["F3:30:L30"]})
2643  call assert_equal('F3:30:L30', g:Xgetlist({'items':1}).items[2].text)
2644  call assert_equal(20, g:Xgetlist({'items':1}).items[1].lnum)
2645  call assert_equal(-1, g:Xsetlist([], 'a', {'efm' : [],
2646				\ 'lines' : ['F1:10:L10']}))
2647endfunc
2648
2649func Test_setexpr()
2650  call Xsetexpr_tests('c')
2651  call Xsetexpr_tests('l')
2652endfunc
2653
2654" Tests for per quickfix/location list directory stack
2655func Xmultidirstack_tests(cchar)
2656  call s:setup_commands(a:cchar)
2657
2658  call g:Xsetlist([], 'f')
2659  Xexpr "" | Xexpr ""
2660
2661  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["Entering dir 'Xone/a'"]})
2662  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["Entering dir 'Xtwo/a'"]})
2663  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["one.txt:3:one one one"]})
2664  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["two.txt:5:two two two"]})
2665
2666  let l1 = g:Xgetlist({'nr':1, 'items':1})
2667  let l2 = g:Xgetlist({'nr':2, 'items':1})
2668  call assert_equal('Xone/a/one.txt', bufname(l1.items[1].bufnr))
2669  call assert_equal(3, l1.items[1].lnum)
2670  call assert_equal('Xtwo/a/two.txt', bufname(l2.items[1].bufnr))
2671  call assert_equal(5, l2.items[1].lnum)
2672endfunc
2673
2674func Test_multidirstack()
2675  call mkdir('Xone/a', 'p')
2676  call mkdir('Xtwo/a', 'p')
2677  let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7']
2678  call writefile(lines, 'Xone/a/one.txt')
2679  call writefile(lines, 'Xtwo/a/two.txt')
2680  let save_efm = &efm
2681  set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f'
2682
2683  call Xmultidirstack_tests('c')
2684  call Xmultidirstack_tests('l')
2685
2686  let &efm = save_efm
2687  call delete('Xone', 'rf')
2688  call delete('Xtwo', 'rf')
2689endfunc
2690
2691" Tests for per quickfix/location list file stack
2692func Xmultifilestack_tests(cchar)
2693  call s:setup_commands(a:cchar)
2694
2695  call g:Xsetlist([], 'f')
2696  Xexpr "" | Xexpr ""
2697
2698  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["[one.txt]"]})
2699  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["[two.txt]"]})
2700  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["(3,5) one one one"]})
2701  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["(5,9) two two two"]})
2702
2703  let l1 = g:Xgetlist({'nr':1, 'items':1})
2704  let l2 = g:Xgetlist({'nr':2, 'items':1})
2705  call assert_equal('one.txt', bufname(l1.items[1].bufnr))
2706  call assert_equal(3, l1.items[1].lnum)
2707  call assert_equal('two.txt', bufname(l2.items[1].bufnr))
2708  call assert_equal(5, l2.items[1].lnum)
2709
2710  " Test for start of a new error line in the same line where a previous
2711  " error line ends with a file stack.
2712  let efm_val = 'Error\ l%l\ in\ %f,'
2713  let efm_val .= '%-P%>(%f%r,Error\ l%l\ in\ %m,%-Q)%r'
2714  let l = g:Xgetlist({'lines' : [
2715	      \ '(one.txt',
2716	      \ 'Error l4 in one.txt',
2717	      \ ') (two.txt',
2718	      \ 'Error l6 in two.txt',
2719	      \ ')',
2720	      \ 'Error l8 in one.txt'
2721	      \ ], 'efm' : efm_val})
2722  call assert_equal(3, len(l.items))
2723  call assert_equal('one.txt', bufname(l.items[0].bufnr))
2724  call assert_equal(4, l.items[0].lnum)
2725  call assert_equal('one.txt', l.items[0].text)
2726  call assert_equal('two.txt', bufname(l.items[1].bufnr))
2727  call assert_equal(6, l.items[1].lnum)
2728  call assert_equal('two.txt', l.items[1].text)
2729  call assert_equal('one.txt', bufname(l.items[2].bufnr))
2730  call assert_equal(8, l.items[2].lnum)
2731  call assert_equal('', l.items[2].text)
2732endfunc
2733
2734func Test_multifilestack()
2735  let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7']
2736  call writefile(lines, 'one.txt')
2737  call writefile(lines, 'two.txt')
2738  let save_efm = &efm
2739  set efm=%+P[%f],(%l\\,%c)\ %m,%-Q
2740
2741  call Xmultifilestack_tests('c')
2742  call Xmultifilestack_tests('l')
2743
2744  let &efm = save_efm
2745  call delete('one.txt')
2746  call delete('two.txt')
2747endfunc
2748
2749" Tests for per buffer 'efm' setting
2750func Test_perbuf_efm()
2751  call writefile(["File1-10-Line10"], 'one.txt')
2752  call writefile(["File2#20#Line20"], 'two.txt')
2753  set efm=%f#%l#%m
2754  new | only
2755  new
2756  setlocal efm=%f-%l-%m
2757  cfile one.txt
2758  wincmd w
2759  caddfile two.txt
2760
2761  let l = getqflist()
2762  call assert_equal(10, l[0].lnum)
2763  call assert_equal('Line20', l[1].text)
2764
2765  set efm&
2766  new | only
2767  call delete('one.txt')
2768  call delete('two.txt')
2769endfunc
2770
2771" Open multiple help windows using ":lhelpgrep
2772" This test used to crash Vim
2773func Test_Multi_LL_Help()
2774    new | only
2775    lhelpgrep window
2776    lopen
2777    e#
2778    lhelpgrep buffer
2779    call assert_equal(3, winnr('$'))
2780    call assert_true(len(getloclist(1)) != 0)
2781    call assert_true(len(getloclist(2)) != 0)
2782    new | only
2783endfunc
2784
2785" Tests for adding new quickfix lists using setqflist()
2786func XaddQf_tests(cchar)
2787  call s:setup_commands(a:cchar)
2788
2789  " Create a new list using ' ' for action
2790  call g:Xsetlist([], 'f')
2791  call g:Xsetlist([], ' ', {'title' : 'Test1'})
2792  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2793  call assert_equal(1, l.nr)
2794  call assert_equal('Test1', l.title)
2795
2796  " Create a new list using ' ' for action and '$' for 'nr'
2797  call g:Xsetlist([], 'f')
2798  call g:Xsetlist([], ' ', {'title' : 'Test2', 'nr' : '$'})
2799  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2800  call assert_equal(1, l.nr)
2801  call assert_equal('Test2', l.title)
2802
2803  " Create a new list using 'a' for action
2804  call g:Xsetlist([], 'f')
2805  call g:Xsetlist([], 'a', {'title' : 'Test3'})
2806  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2807  call assert_equal(1, l.nr)
2808  call assert_equal('Test3', l.title)
2809
2810  " Create a new list using 'a' for action and '$' for 'nr'
2811  call g:Xsetlist([], 'f')
2812  call g:Xsetlist([], 'a', {'title' : 'Test3', 'nr' : '$'})
2813  call g:Xsetlist([], 'a', {'title' : 'Test4'})
2814  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2815  call assert_equal(1, l.nr)
2816  call assert_equal('Test4', l.title)
2817
2818  " Adding a quickfix list should remove all the lists following the current
2819  " list.
2820  Xexpr "" | Xexpr "" | Xexpr ""
2821  silent! 10Xolder
2822  call g:Xsetlist([], ' ', {'title' : 'Test5'})
2823  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2824  call assert_equal(2, l.nr)
2825  call assert_equal('Test5', l.title)
2826
2827  " Add a quickfix list using '$' as the list number.
2828  let lastqf = g:Xgetlist({'nr':'$'}).nr
2829  silent! 99Xolder
2830  call g:Xsetlist([], ' ', {'nr' : '$', 'title' : 'Test6'})
2831  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2832  call assert_equal(lastqf + 1, l.nr)
2833  call assert_equal('Test6', l.title)
2834
2835  " Add a quickfix list using 'nr' set to one more than the quickfix
2836  " list size.
2837  let lastqf = g:Xgetlist({'nr':'$'}).nr
2838  silent! 99Xolder
2839  call g:Xsetlist([], ' ', {'nr' : lastqf + 1, 'title' : 'Test7'})
2840  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2841  call assert_equal(lastqf + 1, l.nr)
2842  call assert_equal('Test7', l.title)
2843
2844  " Add a quickfix list to a stack with 10 lists using 'nr' set to '$'
2845  exe repeat('Xexpr "" |', 9) . 'Xexpr ""'
2846  silent! 99Xolder
2847  call g:Xsetlist([], ' ', {'nr' : '$', 'title' : 'Test8'})
2848  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2849  call assert_equal(10, l.nr)
2850  call assert_equal('Test8', l.title)
2851
2852  " Add a quickfix list using 'nr' set to a value greater than 10
2853  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : 12, 'title' : 'Test9'}))
2854
2855  " Try adding a quickfix list with 'nr' set to a value greater than the
2856  " quickfix list size but less than 10.
2857  call g:Xsetlist([], 'f')
2858  Xexpr "" | Xexpr "" | Xexpr ""
2859  silent! 99Xolder
2860  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : 8, 'title' : 'Test10'}))
2861
2862  " Add a quickfix list using 'nr' set to a some string or list
2863  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : [1,2], 'title' : 'Test11'}))
2864endfunc
2865
2866func Test_add_qf()
2867  call XaddQf_tests('c')
2868  call XaddQf_tests('l')
2869endfunc
2870
2871" Test for getting the quickfix list items from some text without modifying
2872" the quickfix stack
2873func XgetListFromLines(cchar)
2874  call s:setup_commands(a:cchar)
2875  call g:Xsetlist([], 'f')
2876
2877  let l = g:Xgetlist({'lines' : ["File2:20:Line20", "File2:30:Line30"]}).items
2878  call assert_equal(2, len(l))
2879  call assert_equal(30, l[1].lnum)
2880
2881  call assert_equal({}, g:Xgetlist({'lines' : 10}))
2882  call assert_equal({}, g:Xgetlist({'lines' : 'File1:10:Line10'}))
2883  call assert_equal([], g:Xgetlist({'lines' : []}).items)
2884  call assert_equal([], g:Xgetlist({'lines' : [10, 20]}).items)
2885
2886  " Parse text using a custom efm
2887  set efm&
2888  let l = g:Xgetlist({'lines':['File3#30#Line30'], 'efm' : '%f#%l#%m'}).items
2889  call assert_equal('Line30', l[0].text)
2890  let l = g:Xgetlist({'lines':['File3:30:Line30'], 'efm' : '%f-%l-%m'}).items
2891  call assert_equal('File3:30:Line30', l[0].text)
2892  let l = g:Xgetlist({'lines':['File3:30:Line30'], 'efm' : [1,2]})
2893  call assert_equal({}, l)
2894  call assert_fails("call g:Xgetlist({'lines':['abc'], 'efm':'%2'})", 'E376:')
2895  call assert_fails("call g:Xgetlist({'lines':['abc'], 'efm':''})", 'E378:')
2896
2897  " Make sure that the quickfix stack is not modified
2898  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
2899endfunc
2900
2901func Test_get_list_from_lines()
2902  call XgetListFromLines('c')
2903  call XgetListFromLines('l')
2904endfunc
2905
2906" Tests for the quickfix list id
2907func Xqfid_tests(cchar)
2908  call s:setup_commands(a:cchar)
2909
2910  call g:Xsetlist([], 'f')
2911  call assert_equal(0, g:Xgetlist({'id':0}).id)
2912  Xexpr ''
2913  let start_id = g:Xgetlist({'id' : 0}).id
2914  Xexpr '' | Xexpr ''
2915  Xolder
2916  call assert_equal(start_id, g:Xgetlist({'id':0, 'nr':1}).id)
2917  call assert_equal(start_id + 1, g:Xgetlist({'id':0, 'nr':0}).id)
2918  call assert_equal(start_id + 2, g:Xgetlist({'id':0, 'nr':'$'}).id)
2919  call assert_equal(0, g:Xgetlist({'id':0, 'nr':99}).id)
2920  call assert_equal(2, g:Xgetlist({'id':start_id + 1, 'nr':0}).nr)
2921  call assert_equal(0, g:Xgetlist({'id':99, 'nr':0}).id)
2922  call assert_equal(0, g:Xgetlist({'id':"abc", 'nr':0}).id)
2923
2924  call g:Xsetlist([], 'a', {'id':start_id, 'context':[1,2]})
2925  call assert_equal([1,2], g:Xgetlist({'nr':1, 'context':1}).context)
2926  call g:Xsetlist([], 'a', {'id':start_id+1, 'lines':['F1:10:L10']})
2927  call assert_equal('L10', g:Xgetlist({'nr':2, 'items':1}).items[0].text)
2928  call assert_equal(-1, g:Xsetlist([], 'a', {'id':999, 'title':'Vim'}))
2929  call assert_equal(-1, g:Xsetlist([], 'a', {'id':'abc', 'title':'Vim'}))
2930
2931  let qfid = g:Xgetlist({'id':0, 'nr':0})
2932  call g:Xsetlist([], 'f')
2933  call assert_equal(0, g:Xgetlist({'id':qfid, 'nr':0}).id)
2934endfunc
2935
2936func Test_qf_id()
2937  call Xqfid_tests('c')
2938  call Xqfid_tests('l')
2939endfunc
2940
2941func Xqfjump_tests(cchar)
2942  call s:setup_commands(a:cchar)
2943
2944  call writefile(["Line1\tFoo", "Line2"], 'F1')
2945  call writefile(["Line1\tBar", "Line2"], 'F2')
2946  call writefile(["Line1\tBaz", "Line2"], 'F3')
2947
2948  call g:Xsetlist([], 'f')
2949
2950  " Tests for
2951  "   Jumping to a line using a pattern
2952  "   Jumping to a column greater than the last column in a line
2953  "   Jumping to a line greater than the last line in the file
2954  let l = []
2955  for i in range(1, 7)
2956    call add(l, {})
2957  endfor
2958  let l[0].filename='F1'
2959  let l[0].pattern='Line1'
2960  let l[1].filename='F2'
2961  let l[1].pattern='Line1'
2962  let l[2].filename='F3'
2963  let l[2].pattern='Line1'
2964  let l[3].filename='F3'
2965  let l[3].lnum=1
2966  let l[3].col=9
2967  let l[3].vcol=1
2968  let l[4].filename='F3'
2969  let l[4].lnum=99
2970  let l[5].filename='F3'
2971  let l[5].lnum=1
2972  let l[5].col=99
2973  let l[5].vcol=1
2974  let l[6].filename='F3'
2975  let l[6].pattern='abcxyz'
2976
2977  call g:Xsetlist([], ' ', {'items' : l})
2978  Xopen | only
2979  2Xnext
2980  call assert_equal(3, g:Xgetlist({'idx' : 0}).idx)
2981  call assert_equal('F3', bufname('%'))
2982  Xnext
2983  call assert_equal(7, col('.'))
2984  Xnext
2985  call assert_equal(2, line('.'))
2986  Xnext
2987  call assert_equal(9, col('.'))
2988  2
2989  Xnext
2990  call assert_equal(2, line('.'))
2991
2992  if a:cchar == 'l'
2993    " When jumping to a location list entry in the location list window and
2994    " no usable windows are available, then a new window should be opened.
2995    enew! | new | only
2996    call g:Xsetlist([], 'f')
2997    setlocal buftype=nofile
2998    new
2999    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']})
3000    Xopen
3001    let winid = win_getid()
3002    wincmd p
3003    close
3004    call win_gotoid(winid)
3005    Xnext
3006    call assert_equal(3, winnr('$'))
3007    call assert_equal(1, winnr())
3008    call assert_equal(2, line('.'))
3009
3010    " When jumping to an entry in the location list window and the window
3011    " associated with the location list is not present and a window containing
3012    " the file is already present, then that window should be used.
3013    close
3014    belowright new
3015    call g:Xsetlist([], 'f')
3016    edit F3
3017    call win_gotoid(winid)
3018    Xlast
3019    call assert_equal(3, winnr())
3020    call assert_equal(6, g:Xgetlist({'size' : 1}).size)
3021    call assert_equal(winid, g:Xgetlist({'winid' : 1}).winid)
3022  endif
3023
3024  " Cleanup
3025  enew!
3026  new | only
3027
3028  call delete('F1')
3029  call delete('F2')
3030  call delete('F3')
3031endfunc
3032
3033func Test_qfjump()
3034  call Xqfjump_tests('c')
3035  call Xqfjump_tests('l')
3036endfunc
3037
3038" Tests for the getqflist() and getloclist() functions when the list is not
3039" present or is empty
3040func Xgetlist_empty_tests(cchar)
3041  call s:setup_commands(a:cchar)
3042
3043  " Empty quickfix stack
3044  call g:Xsetlist([], 'f')
3045  call assert_equal('', g:Xgetlist({'context' : 0}).context)
3046  call assert_equal(0, g:Xgetlist({'id' : 0}).id)
3047  call assert_equal(0, g:Xgetlist({'idx' : 0}).idx)
3048  call assert_equal([], g:Xgetlist({'items' : 0}).items)
3049  call assert_equal(0, g:Xgetlist({'nr' : 0}).nr)
3050  call assert_equal(0, g:Xgetlist({'size' : 0}).size)
3051  call assert_equal('', g:Xgetlist({'title' : 0}).title)
3052  call assert_equal(0, g:Xgetlist({'winid' : 0}).winid)
3053  call assert_equal(0, g:Xgetlist({'changedtick' : 0}).changedtick)
3054  if a:cchar == 'c'
3055    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0,
3056		  \ 'items' : [], 'nr' : 0, 'size' : 0,
3057		  \ 'title' : '', 'winid' : 0, 'changedtick': 0},
3058		  \ g:Xgetlist({'all' : 0}))
3059  else
3060    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0,
3061		\ 'items' : [], 'nr' : 0, 'size' : 0, 'title' : '',
3062		\ 'winid' : 0, 'changedtick': 0, 'filewinid' : 0},
3063		\ g:Xgetlist({'all' : 0}))
3064  endif
3065
3066  " Quickfix window with empty stack
3067  silent! Xopen
3068  let qfwinid = (a:cchar == 'c') ? win_getid() : 0
3069  call assert_equal(qfwinid, g:Xgetlist({'winid' : 0}).winid)
3070  Xclose
3071
3072  " Empty quickfix list
3073  Xexpr ""
3074  call assert_equal('', g:Xgetlist({'context' : 0}).context)
3075  call assert_notequal(0, g:Xgetlist({'id' : 0}).id)
3076  call assert_equal(0, g:Xgetlist({'idx' : 0}).idx)
3077  call assert_equal([], g:Xgetlist({'items' : 0}).items)
3078  call assert_notequal(0, g:Xgetlist({'nr' : 0}).nr)
3079  call assert_equal(0, g:Xgetlist({'size' : 0}).size)
3080  call assert_notequal('', g:Xgetlist({'title' : 0}).title)
3081  call assert_equal(0, g:Xgetlist({'winid' : 0}).winid)
3082  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3083
3084  let qfid = g:Xgetlist({'id' : 0}).id
3085  call g:Xsetlist([], 'f')
3086
3087  " Non-existing quickfix identifier
3088  call assert_equal('', g:Xgetlist({'id' : qfid, 'context' : 0}).context)
3089  call assert_equal(0, g:Xgetlist({'id' : qfid}).id)
3090  call assert_equal(0, g:Xgetlist({'id' : qfid, 'idx' : 0}).idx)
3091  call assert_equal([], g:Xgetlist({'id' : qfid, 'items' : 0}).items)
3092  call assert_equal(0, g:Xgetlist({'id' : qfid, 'nr' : 0}).nr)
3093  call assert_equal(0, g:Xgetlist({'id' : qfid, 'size' : 0}).size)
3094  call assert_equal('', g:Xgetlist({'id' : qfid, 'title' : 0}).title)
3095  call assert_equal(0, g:Xgetlist({'id' : qfid, 'winid' : 0}).winid)
3096  call assert_equal(0, g:Xgetlist({'id' : qfid, 'changedtick' : 0}).changedtick)
3097  if a:cchar == 'c'
3098    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
3099		\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
3100		\ 'changedtick' : 0}, g:Xgetlist({'id' : qfid, 'all' : 0}))
3101  else
3102    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
3103		\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
3104		\ 'changedtick' : 0, 'filewinid' : 0},
3105		\ g:Xgetlist({'id' : qfid, 'all' : 0}))
3106  endif
3107
3108  " Non-existing quickfix list number
3109  call assert_equal('', g:Xgetlist({'nr' : 5, 'context' : 0}).context)
3110  call assert_equal(0, g:Xgetlist({'nr' : 5}).nr)
3111  call assert_equal(0, g:Xgetlist({'nr' : 5, 'idx' : 0}).idx)
3112  call assert_equal([], g:Xgetlist({'nr' : 5, 'items' : 0}).items)
3113  call assert_equal(0, g:Xgetlist({'nr' : 5, 'id' : 0}).id)
3114  call assert_equal(0, g:Xgetlist({'nr' : 5, 'size' : 0}).size)
3115  call assert_equal('', g:Xgetlist({'nr' : 5, 'title' : 0}).title)
3116  call assert_equal(0, g:Xgetlist({'nr' : 5, 'winid' : 0}).winid)
3117  call assert_equal(0, g:Xgetlist({'nr' : 5, 'changedtick' : 0}).changedtick)
3118  if a:cchar == 'c'
3119    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
3120		\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
3121		\ 'changedtick' : 0}, g:Xgetlist({'nr' : 5, 'all' : 0}))
3122  else
3123    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
3124		\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
3125		\ 'changedtick' : 0, 'filewinid' : 0},
3126		\ g:Xgetlist({'nr' : 5, 'all' : 0}))
3127  endif
3128endfunc
3129
3130func Test_getqflist()
3131  call Xgetlist_empty_tests('c')
3132  call Xgetlist_empty_tests('l')
3133endfunc
3134
3135func Test_getqflist_invalid_nr()
3136  " The following commands used to crash Vim
3137  cexpr ""
3138  call getqflist({'nr' : $XXX_DOES_NOT_EXIST_XXX})
3139
3140  " Cleanup
3141  call setqflist([], 'r')
3142endfunc
3143
3144" Tests for the quickfix/location list changedtick
3145func Xqftick_tests(cchar)
3146  call s:setup_commands(a:cchar)
3147
3148  call g:Xsetlist([], 'f')
3149
3150  Xexpr "F1:10:Line10"
3151  let qfid = g:Xgetlist({'id' : 0}).id
3152  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3153  Xaddexpr "F2:20:Line20\nF2:21:Line21"
3154  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
3155  call g:Xsetlist([], 'a', {'lines' : ["F3:30:Line30", "F3:31:Line31"]})
3156  call assert_equal(3, g:Xgetlist({'changedtick' : 0}).changedtick)
3157  call g:Xsetlist([], 'r', {'lines' : ["F4:40:Line40"]})
3158  call assert_equal(4, g:Xgetlist({'changedtick' : 0}).changedtick)
3159  call g:Xsetlist([], 'a', {'title' : 'New Title'})
3160  call assert_equal(5, g:Xgetlist({'changedtick' : 0}).changedtick)
3161
3162  enew!
3163  call append(0, ["F5:50:L50", "F6:60:L60"])
3164  Xaddbuffer
3165  call assert_equal(6, g:Xgetlist({'changedtick' : 0}).changedtick)
3166  enew!
3167
3168  call g:Xsetlist([], 'a', {'context' : {'bus' : 'pci'}})
3169  call assert_equal(7, g:Xgetlist({'changedtick' : 0}).changedtick)
3170  call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'},
3171	      \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], 'a')
3172  call assert_equal(8, g:Xgetlist({'changedtick' : 0}).changedtick)
3173  call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'},
3174	      \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], ' ')
3175  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3176  call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'},
3177	      \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], 'r')
3178  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
3179
3180  call writefile(["F8:80:L80", "F8:81:L81"], "Xone")
3181  Xfile Xone
3182  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3183  Xaddfile Xone
3184  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
3185
3186  " Test case for updating a non-current quickfix list
3187  call g:Xsetlist([], 'f')
3188  Xexpr "F1:1:L1"
3189  Xexpr "F2:2:L2"
3190  call g:Xsetlist([], 'a', {'nr' : 1, "lines" : ["F10:10:L10"]})
3191  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3192  call assert_equal(2, g:Xgetlist({'nr' : 1, 'changedtick' : 0}).changedtick)
3193
3194  call delete("Xone")
3195endfunc
3196
3197func Test_qf_tick()
3198  call Xqftick_tests('c')
3199  call Xqftick_tests('l')
3200endfunc
3201
3202" Test helpgrep with lang specifier
3203func Xtest_helpgrep_with_lang_specifier(cchar)
3204  call s:setup_commands(a:cchar)
3205  Xhelpgrep Vim@en
3206  call assert_equal('help', &filetype)
3207  call assert_notequal(0, g:Xgetlist({'nr' : '$'}).nr)
3208  new | only
3209endfunc
3210
3211func Test_helpgrep_with_lang_specifier()
3212  call Xtest_helpgrep_with_lang_specifier('c')
3213  call Xtest_helpgrep_with_lang_specifier('l')
3214endfunc
3215
3216" The following test used to crash Vim.
3217" Open the location list window and close the regular window associated with
3218" the location list. When the garbage collection runs now, it incorrectly
3219" marks the location list context as not in use and frees the context.
3220func Test_ll_window_ctx()
3221  call setloclist(0, [], 'f')
3222  call setloclist(0, [], 'a', {'context' : []})
3223  lopen | only
3224  call test_garbagecollect_now()
3225  echo getloclist(0, {'context' : 1}).context
3226  enew | only
3227endfunc
3228
3229" The following test used to crash vim
3230func Test_lfile_crash()
3231  sp Xtest
3232  au QuickFixCmdPre * bw
3233  call assert_fails('lfile', 'E40')
3234  au! QuickFixCmdPre
3235endfunc
3236
3237" The following test used to crash vim
3238func Test_lbuffer_crash()
3239  sv Xtest
3240  augroup QF_Test
3241    au!
3242    au * * bw
3243  augroup END
3244  lbuffer
3245  augroup QF_Test
3246    au!
3247  augroup END
3248endfunc
3249
3250" The following test used to crash vim
3251func Test_lexpr_crash()
3252  augroup QF_Test
3253    au!
3254    au * * call setloclist(0, [], 'f')
3255  augroup END
3256  lexpr ""
3257  augroup QF_Test
3258    au!
3259  augroup END
3260
3261  enew | only
3262  augroup QF_Test
3263    au!
3264    au BufNew * call setloclist(0, [], 'f')
3265  augroup END
3266  lexpr 'x:1:x'
3267  augroup QF_Test
3268    au!
3269  augroup END
3270
3271  enew | only
3272  lexpr ''
3273  lopen
3274  augroup QF_Test
3275    au!
3276    au FileType * call setloclist(0, [], 'f')
3277  augroup END
3278  lexpr ''
3279  augroup QF_Test
3280    au!
3281  augroup END
3282endfunc
3283
3284" The following test used to crash Vim
3285func Test_lvimgrep_crash()
3286  sv Xtest
3287  augroup QF_Test
3288    au!
3289    au * * call setloclist(0, [], 'f')
3290  augroup END
3291  lvimgrep quickfix test_quickfix.vim
3292  augroup QF_Test
3293    au!
3294  augroup END
3295
3296  new | only
3297  augroup QF_Test
3298    au!
3299    au BufEnter * call setloclist(0, [], 'r')
3300  augroup END
3301  call assert_fails('lvimgrep Test_lvimgrep_crash *', 'E926:')
3302  augroup QF_Test
3303    au!
3304  augroup END
3305
3306  enew | only
3307endfunc
3308
3309" Test for the position of the quickfix and location list window
3310func Test_qfwin_pos()
3311  " Open two windows
3312  new | only
3313  new
3314  cexpr ['F1:10:L10']
3315  copen
3316  " Quickfix window should be the bottom most window
3317  call assert_equal(3, winnr())
3318  close
3319  " Open at the very top
3320  wincmd t
3321  topleft copen
3322  call assert_equal(1, winnr())
3323  close
3324  " open left of the current window
3325  wincmd t
3326  below new
3327  leftabove copen
3328  call assert_equal(2, winnr())
3329  close
3330  " open right of the current window
3331  rightbelow copen
3332  call assert_equal(3, winnr())
3333  close
3334endfunc
3335
3336" Tests for quickfix/location lists changed by autocommands when
3337" :vimgrep/:lvimgrep commands are running.
3338func Test_vimgrep_autocmd()
3339  call setqflist([], 'f')
3340  call writefile(['stars'], 'Xtest1.txt')
3341  call writefile(['stars'], 'Xtest2.txt')
3342
3343  " Test 1:
3344  " When searching for a pattern using :vimgrep, if the quickfix list is
3345  " changed by an autocmd, the results should be added to the correct quickfix
3346  " list.
3347  autocmd BufRead Xtest2.txt cexpr '' | cexpr ''
3348  silent vimgrep stars Xtest*.txt
3349  call assert_equal(1, getqflist({'nr' : 0}).nr)
3350  call assert_equal(3, getqflist({'nr' : '$'}).nr)
3351  call assert_equal('Xtest2.txt', bufname(getqflist()[1].bufnr))
3352  au! BufRead Xtest2.txt
3353
3354  " Test 2:
3355  " When searching for a pattern using :vimgrep, if the quickfix list is
3356  " freed, then a error should be given.
3357  silent! %bwipe!
3358  call setqflist([], 'f')
3359  autocmd BufRead Xtest2.txt for i in range(10) | cexpr '' | endfor
3360  call assert_fails('vimgrep stars Xtest*.txt', 'E925:')
3361  au! BufRead Xtest2.txt
3362
3363  " Test 3:
3364  " When searching for a pattern using :lvimgrep, if the location list is
3365  " freed, then the command should error out.
3366  silent! %bwipe!
3367  let g:save_winid = win_getid()
3368  autocmd BufRead Xtest2.txt call setloclist(g:save_winid, [], 'f')
3369  call assert_fails('lvimgrep stars Xtest*.txt', 'E926:')
3370  au! BufRead Xtest2.txt
3371
3372  call delete('Xtest1.txt')
3373  call delete('Xtest2.txt')
3374  call setqflist([], 'f')
3375endfunc
3376
3377" The following test used to crash Vim
3378func Test_lhelpgrep_autocmd()
3379  lhelpgrep quickfix
3380  autocmd QuickFixCmdPost * call setloclist(0, [], 'f')
3381  lhelpgrep buffer
3382  call assert_equal('help', &filetype)
3383  call assert_equal(0, getloclist(0, {'nr' : '$'}).nr)
3384  lhelpgrep tabpage
3385  call assert_equal('help', &filetype)
3386  call assert_equal(1, getloclist(0, {'nr' : '$'}).nr)
3387  au! QuickFixCmdPost
3388
3389  new | only
3390  augroup QF_Test
3391    au!
3392    au BufEnter * call setqflist([], 'f')
3393  augroup END
3394  call assert_fails('helpgrep quickfix', 'E925:')
3395  augroup QF_Test
3396    au! BufEnter
3397  augroup END
3398
3399  new | only
3400  augroup QF_Test
3401    au!
3402    au BufEnter * call setqflist([], 'r')
3403  augroup END
3404  call assert_fails('helpgrep quickfix', 'E925:')
3405  augroup QF_Test
3406    au! BufEnter
3407  augroup END
3408
3409  new | only
3410  augroup QF_Test
3411    au!
3412    au BufEnter * call setloclist(0, [], 'r')
3413  augroup END
3414  call assert_fails('lhelpgrep quickfix', 'E926:')
3415  augroup QF_Test
3416    au! BufEnter
3417  augroup END
3418
3419  new | only
3420endfunc
3421
3422" Test for shortening/simplifying the file name when opening the
3423" quickfix window or when displaying the quickfix list
3424func Test_shorten_fname()
3425  if !has('unix')
3426    return
3427  endif
3428  %bwipe
3429  " Create a quickfix list with a absolute path filename
3430  let fname = getcwd() . '/test_quickfix.vim'
3431  call setqflist([], ' ', {'lines':[fname . ":20:Line20"], 'efm':'%f:%l:%m'})
3432  call assert_equal(fname, bufname('test_quickfix.vim'))
3433  " Opening the quickfix window should simplify the file path
3434  cwindow
3435  call assert_equal('test_quickfix.vim', bufname('test_quickfix.vim'))
3436  cclose
3437  %bwipe
3438  " Create a quickfix list with a absolute path filename
3439  call setqflist([], ' ', {'lines':[fname . ":20:Line20"], 'efm':'%f:%l:%m'})
3440  call assert_equal(fname, bufname('test_quickfix.vim'))
3441  " Displaying the quickfix list should simplify the file path
3442  silent! clist
3443  call assert_equal('test_quickfix.vim', bufname('test_quickfix.vim'))
3444endfunc
3445
3446" Quickfix title tests
3447" In the below tests, 'exe "cmd"' is used to invoke the quickfix commands.
3448" Otherwise due to indentation, the title is set with spaces at the beginning
3449" of the command.
3450func Test_qftitle()
3451  call writefile(["F1:1:Line1"], 'Xerr')
3452
3453  " :cexpr
3454  exe "cexpr readfile('Xerr')"
3455  call assert_equal(":cexpr readfile('Xerr')", getqflist({'title' : 1}).title)
3456
3457  " :cgetexpr
3458  exe "cgetexpr readfile('Xerr')"
3459  call assert_equal(":cgetexpr readfile('Xerr')",
3460					\ getqflist({'title' : 1}).title)
3461
3462  " :caddexpr
3463  call setqflist([], 'f')
3464  exe "caddexpr readfile('Xerr')"
3465  call assert_equal(":caddexpr readfile('Xerr')",
3466					\ getqflist({'title' : 1}).title)
3467
3468  " :cbuffer
3469  new Xerr
3470  exe "cbuffer"
3471  call assert_equal(':cbuffer (Xerr)', getqflist({'title' : 1}).title)
3472
3473  " :cgetbuffer
3474  edit Xerr
3475  exe "cgetbuffer"
3476  call assert_equal(':cgetbuffer (Xerr)', getqflist({'title' : 1}).title)
3477
3478  " :caddbuffer
3479  call setqflist([], 'f')
3480  edit Xerr
3481  exe "caddbuffer"
3482  call assert_equal(':caddbuffer (Xerr)', getqflist({'title' : 1}).title)
3483
3484  " :cfile
3485  exe "cfile Xerr"
3486  call assert_equal(':cfile Xerr', getqflist({'title' : 1}).title)
3487
3488  " :cgetfile
3489  exe "cgetfile Xerr"
3490  call assert_equal(':cgetfile Xerr', getqflist({'title' : 1}).title)
3491
3492  " :caddfile
3493  call setqflist([], 'f')
3494  exe "caddfile Xerr"
3495  call assert_equal(':caddfile Xerr', getqflist({'title' : 1}).title)
3496
3497  " :grep
3498  set grepprg=internal
3499  exe "grep F1 Xerr"
3500  call assert_equal(':grep F1 Xerr', getqflist({'title' : 1}).title)
3501
3502  " :grepadd
3503  call setqflist([], 'f')
3504  exe "grepadd F1 Xerr"
3505  call assert_equal(':grepadd F1 Xerr', getqflist({'title' : 1}).title)
3506  set grepprg&vim
3507
3508  " :vimgrep
3509  exe "vimgrep F1 Xerr"
3510  call assert_equal(':vimgrep F1 Xerr', getqflist({'title' : 1}).title)
3511
3512  " :vimgrepadd
3513  call setqflist([], 'f')
3514  exe "vimgrepadd F1 Xerr"
3515  call assert_equal(':vimgrepadd F1 Xerr', getqflist({'title' : 1}).title)
3516
3517  call setqflist(['F1:10:L10'], ' ')
3518  call assert_equal(':setqflist()', getqflist({'title' : 1}).title)
3519
3520  call setqflist([], 'f')
3521  call setqflist(['F1:10:L10'], 'a')
3522  call assert_equal(':setqflist()', getqflist({'title' : 1}).title)
3523
3524  call setqflist([], 'f')
3525  call setqflist(['F1:10:L10'], 'r')
3526  call assert_equal(':setqflist()', getqflist({'title' : 1}).title)
3527
3528  close
3529  call delete('Xerr')
3530
3531  call setqflist([], ' ', {'title' : 'Errors'})
3532  copen
3533  call assert_equal('Errors', w:quickfix_title)
3534  call setqflist([], 'r', {'items' : [{'filename' : 'a.c', 'lnum' : 10}]})
3535  call assert_equal('Errors', w:quickfix_title)
3536  cclose
3537endfunc
3538
3539func Test_lbuffer_with_bwipe()
3540  new
3541  new
3542  augroup nasty
3543    au * * bwipe
3544  augroup END
3545  lbuffer
3546  augroup nasty
3547    au!
3548  augroup END
3549endfunc
3550
3551" Test for an autocmd freeing the quickfix/location list when cexpr/lexpr is
3552" running
3553func Xexpr_acmd_freelist(cchar)
3554  call s:setup_commands(a:cchar)
3555
3556  " This was using freed memory.
3557  augroup nasty
3558    au * * call g:Xsetlist([], 'f')
3559  augroup END
3560  Xexpr "x"
3561  augroup nasty
3562    au!
3563  augroup END
3564endfunc
3565
3566func Test_cexpr_acmd_freelist()
3567  call Xexpr_acmd_freelist('c')
3568  call Xexpr_acmd_freelist('l')
3569endfunc
3570
3571" Test for commands that create a new quickfix/location list and jump to the
3572" first error automatically.
3573func Xjumpto_first_error_test(cchar)
3574  call s:setup_commands(a:cchar)
3575
3576  call s:create_test_file('Xtestfile1')
3577  call s:create_test_file('Xtestfile2')
3578  let l = ['Xtestfile1:2:Line2', 'Xtestfile2:4:Line4']
3579
3580  " Test for cexpr/lexpr
3581  enew
3582  Xexpr l
3583  call assert_equal('Xtestfile1', bufname(''))
3584  call assert_equal(2, line('.'))
3585
3586  " Test for cfile/lfile
3587  enew
3588  call writefile(l, 'Xerr')
3589  Xfile Xerr
3590  call assert_equal('Xtestfile1', bufname(''))
3591  call assert_equal(2, line('.'))
3592
3593  " Test for cbuffer/lbuffer
3594  edit Xerr
3595  Xbuffer
3596  call assert_equal('Xtestfile1', bufname(''))
3597  call assert_equal(2, line('.'))
3598
3599  call delete('Xerr')
3600  call delete('Xtestfile1')
3601  call delete('Xtestfile2')
3602endfunc
3603
3604func Test_jumpto_first_error()
3605  call Xjumpto_first_error_test('c')
3606  call Xjumpto_first_error_test('l')
3607endfunc
3608
3609" Test for a quickfix autocmd changing the quickfix/location list before
3610" jumping to the first error in the new list.
3611func Xautocmd_changelist(cchar)
3612  call s:setup_commands(a:cchar)
3613
3614  " Test for cfile/lfile
3615  call s:create_test_file('Xtestfile1')
3616  call s:create_test_file('Xtestfile2')
3617  Xexpr 'Xtestfile1:2:Line2'
3618  autocmd QuickFixCmdPost * Xolder
3619  call writefile(['Xtestfile2:4:Line4'], 'Xerr')
3620  Xfile Xerr
3621  call assert_equal('Xtestfile2', bufname(''))
3622  call assert_equal(4, line('.'))
3623  autocmd! QuickFixCmdPost
3624
3625  " Test for cbuffer/lbuffer
3626  call g:Xsetlist([], 'f')
3627  Xexpr 'Xtestfile1:2:Line2'
3628  autocmd QuickFixCmdPost * Xolder
3629  call writefile(['Xtestfile2:4:Line4'], 'Xerr')
3630  edit Xerr
3631  Xbuffer
3632  call assert_equal('Xtestfile2', bufname(''))
3633  call assert_equal(4, line('.'))
3634  autocmd! QuickFixCmdPost
3635
3636  " Test for cexpr/lexpr
3637  call g:Xsetlist([], 'f')
3638  Xexpr 'Xtestfile1:2:Line2'
3639  autocmd QuickFixCmdPost * Xolder
3640  Xexpr 'Xtestfile2:4:Line4'
3641  call assert_equal('Xtestfile2', bufname(''))
3642  call assert_equal(4, line('.'))
3643  autocmd! QuickFixCmdPost
3644
3645  " The grepprg may not be set on non-Unix systems
3646  if has('unix')
3647    " Test for grep/lgrep
3648    call g:Xsetlist([], 'f')
3649    Xexpr 'Xtestfile1:2:Line2'
3650    autocmd QuickFixCmdPost * Xolder
3651    silent Xgrep Line5 Xtestfile2
3652    call assert_equal('Xtestfile2', bufname(''))
3653    call assert_equal(5, line('.'))
3654    autocmd! QuickFixCmdPost
3655  endif
3656
3657  " Test for vimgrep/lvimgrep
3658  call g:Xsetlist([], 'f')
3659  Xexpr 'Xtestfile1:2:Line2'
3660  autocmd QuickFixCmdPost * Xolder
3661  silent Xvimgrep Line5 Xtestfile2
3662  call assert_equal('Xtestfile2', bufname(''))
3663  call assert_equal(5, line('.'))
3664  autocmd! QuickFixCmdPost
3665
3666  " Test for autocommands clearing the quickfix list before jumping to the
3667  " first error. This should not result in an error
3668  autocmd QuickFixCmdPost * call g:Xsetlist([], 'r')
3669  let v:errmsg = ''
3670  " Test for cfile/lfile
3671  Xfile Xerr
3672  call assert_true(v:errmsg !~# 'E42:')
3673  " Test for cbuffer/lbuffer
3674  edit Xerr
3675  Xbuffer
3676  call assert_true(v:errmsg !~# 'E42:')
3677  " Test for cexpr/lexpr
3678  Xexpr 'Xtestfile2:4:Line4'
3679  call assert_true(v:errmsg !~# 'E42:')
3680  " Test for grep/lgrep
3681  " The grepprg may not be set on non-Unix systems
3682  if has('unix')
3683    silent Xgrep Line5 Xtestfile2
3684    call assert_true(v:errmsg !~# 'E42:')
3685  endif
3686  " Test for vimgrep/lvimgrep
3687  call assert_fails('silent Xvimgrep Line5 Xtestfile2', 'E480:')
3688  autocmd! QuickFixCmdPost
3689
3690  call delete('Xerr')
3691  call delete('Xtestfile1')
3692  call delete('Xtestfile2')
3693endfunc
3694
3695func Test_autocmd_changelist()
3696  call Xautocmd_changelist('c')
3697  call Xautocmd_changelist('l')
3698endfunc
3699
3700" Tests for the ':filter /pat/ clist' command
3701func Test_filter_clist()
3702  cexpr ['Xfile1:10:10:Line 10', 'Xfile2:15:15:Line 15']
3703  call assert_equal([' 2 Xfile2:15 col 15: Line 15'],
3704			\ split(execute('filter /Line 15/ clist'), "\n"))
3705  call assert_equal([' 1 Xfile1:10 col 10: Line 10'],
3706			\ split(execute('filter /Xfile1/ clist'), "\n"))
3707  call assert_equal([], split(execute('filter /abc/ clist'), "\n"))
3708
3709  call setqflist([{'module' : 'abc', 'pattern' : 'pat1'},
3710			\ {'module' : 'pqr', 'pattern' : 'pat2'}], ' ')
3711  call assert_equal([' 2 pqr:pat2:  '],
3712			\ split(execute('filter /pqr/ clist'), "\n"))
3713  call assert_equal([' 1 abc:pat1:  '],
3714			\ split(execute('filter /pat1/ clist'), "\n"))
3715endfunc
3716
3717" Tests for the "CTRL-W <CR>" command.
3718func Xview_result_split_tests(cchar)
3719  call s:setup_commands(a:cchar)
3720
3721  " Test that "CTRL-W <CR>" in a qf/ll window fails with empty list.
3722  call g:Xsetlist([])
3723  Xopen
3724  let l:win_count = winnr('$')
3725  call assert_fails('execute "normal! \<C-W>\<CR>"', 'E42')
3726  call assert_equal(l:win_count, winnr('$'))
3727  Xclose
3728endfunc
3729
3730func Test_view_result_split()
3731  call Xview_result_split_tests('c')
3732  call Xview_result_split_tests('l')
3733endfunc
3734
3735" Test that :cc sets curswant
3736func Test_curswant()
3737  helpgrep quickfix
3738  normal! llll
3739  1cc
3740  call assert_equal(getcurpos()[4], virtcol('.'))
3741  cclose | helpclose
3742endfunc
3743
3744" Test for opening a file from the quickfix window using CTRL-W <Enter>
3745" doesn't leave an empty buffer around.
3746func Test_splitview()
3747  call s:create_test_file('Xtestfile1')
3748  call s:create_test_file('Xtestfile2')
3749  new | only
3750  let last_bufnr = bufnr('Test_sv_1', 1)
3751  let l = ['Xtestfile1:2:Line2', 'Xtestfile2:4:Line4']
3752  cgetexpr l
3753  copen
3754  let numbufs = len(getbufinfo())
3755  exe "normal \<C-W>\<CR>"
3756  copen
3757  exe "normal j\<C-W>\<CR>"
3758  " Make sure new empty buffers are not created
3759  call assert_equal(numbufs, len(getbufinfo()))
3760  " Creating a new buffer should use the next available buffer number
3761  call assert_equal(last_bufnr + 4, bufnr("Test_sv_2", 1))
3762  bwipe Test_sv_1
3763  bwipe Test_sv_2
3764  new | only
3765
3766  " When split opening files from location list window, make sure that two
3767  " windows doesn't refer to the same location list
3768  lgetexpr l
3769  let locid = getloclist(0, {'id' : 0}).id
3770  lopen
3771  exe "normal \<C-W>\<CR>"
3772  call assert_notequal(locid, getloclist(0, {'id' : 0}).id)
3773  call assert_equal(0, getloclist(0, {'winid' : 0}).winid)
3774  new | only
3775
3776  " When split opening files from a helpgrep location list window, a new help
3777  " window should be opend with a copy of the location list.
3778  lhelpgrep window
3779  let locid = getloclist(0, {'id' : 0}).id
3780  lwindow
3781  exe "normal j\<C-W>\<CR>"
3782  call assert_notequal(locid, getloclist(0, {'id' : 0}).id)
3783  call assert_equal(0, getloclist(0, {'winid' : 0}).winid)
3784  new | only
3785
3786  call delete('Xtestfile1')
3787  call delete('Xtestfile2')
3788endfunc
3789