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:')
561endfunc
562
563func Test_helpgrep()
564  call s:test_xhelpgrep('c')
565  helpclose
566  call s:test_xhelpgrep('l')
567endfunc
568
569func Test_errortitle()
570  augroup QfBufWinEnter
571    au!
572    au BufWinEnter * :let g:a=get(w:, 'quickfix_title', 'NONE')
573  augroup END
574  copen
575  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'')'}]
576  call setqflist(a)
577  call assert_equal(':setqflist()', g:a)
578  augroup QfBufWinEnter
579    au!
580  augroup END
581  augroup! QfBufWinEnter
582endfunc
583
584func Test_vimgreptitle()
585  augroup QfBufWinEnter
586    au!
587    au BufWinEnter * :let g:a=get(w:, 'quickfix_title', 'NONE')
588  augroup END
589  try
590    vimgrep /pattern/j file
591  catch /E480/
592  endtry
593  copen
594  call assert_equal(':    vimgrep /pattern/j file', g:a)
595  augroup QfBufWinEnter
596    au!
597  augroup END
598  augroup! QfBufWinEnter
599endfunc
600
601func XqfTitleTests(cchar)
602  call s:setup_commands(a:cchar)
603
604  Xgetexpr ['file:1:1:message']
605  let l = g:Xgetlist()
606  if a:cchar == 'c'
607    call setqflist(l, 'r')
608  else
609    call setloclist(0, l, 'r')
610  endif
611
612  Xopen
613  if a:cchar == 'c'
614    let title = ':setqflist()'
615  else
616    let title = ':setloclist()'
617  endif
618  call assert_equal(title, w:quickfix_title)
619  Xclose
620endfunc
621
622" Tests for quickfix window's title
623func Test_qf_title()
624  call XqfTitleTests('c')
625  call XqfTitleTests('l')
626endfunc
627
628" Tests for 'errorformat'
629func Test_efm()
630  let save_efm = &efm
631  set efm=%EEEE%m,%WWWW%m,%+CCCC%.%#,%-GGGG%.%#
632  cgetexpr ['WWWW', 'EEEE', 'CCCC']
633  let l = strtrans(string(map(getqflist(), '[v:val.text, v:val.valid]')))
634  call assert_equal("[['W', 1], ['E^@CCCC', 1]]", l)
635  cgetexpr ['WWWW', 'GGGG', 'EEEE', 'CCCC']
636  let l = strtrans(string(map(getqflist(), '[v:val.text, v:val.valid]')))
637  call assert_equal("[['W', 1], ['E^@CCCC', 1]]", l)
638  cgetexpr ['WWWW', 'GGGG', 'ZZZZ', 'EEEE', 'CCCC', 'YYYY']
639  let l = strtrans(string(map(getqflist(), '[v:val.text, v:val.valid]')))
640  call assert_equal("[['W', 1], ['ZZZZ', 0], ['E^@CCCC', 1], ['YYYY', 0]]", l)
641  let &efm = save_efm
642endfunc
643
644" This will test for problems in quickfix:
645" A. incorrectly copying location lists which caused the location list to show
646"    a different name than the file that was actually being displayed.
647" B. not reusing the window for which the location list window is opened but
648"    instead creating new windows.
649" C. make sure that the location list window is not reused instead of the
650"    window it belongs to.
651"
652" Set up the test environment:
653func ReadTestProtocol(name)
654  let base = substitute(a:name, '\v^test://(.*)%(\.[^.]+)?', '\1', '')
655  let word = substitute(base, '\v(.*)\..*', '\1', '')
656
657  setl modifiable
658  setl noreadonly
659  setl noswapfile
660  setl bufhidden=delete
661  %del _
662  " For problem 2:
663  " 'buftype' has to be set to reproduce the constant opening of new windows
664  setl buftype=nofile
665
666  call setline(1, word)
667
668  setl nomodified
669  setl nomodifiable
670  setl readonly
671  exe 'doautocmd BufRead ' . substitute(a:name, '\v^test://(.*)', '\1', '')
672endfunc
673
674func Test_locationlist()
675    enew
676
677    augroup testgroup
678      au!
679      autocmd BufReadCmd test://* call ReadTestProtocol(expand("<amatch>"))
680    augroup END
681
682    let words = [ "foo", "bar", "baz", "quux", "shmoo", "spam", "eggs" ]
683
684    let qflist = []
685    for word in words
686      call add(qflist, {'filename': 'test://' . word . '.txt', 'text': 'file ' . word . '.txt', })
687      " NOTE: problem 1:
688      " intentionally not setting 'lnum' so that the quickfix entries are not
689      " valid
690      call setloclist(0, qflist, ' ')
691    endfor
692
693    " Test A
694    lrewind
695    enew
696    lopen
697    4lnext
698    vert split
699    wincmd L
700    lopen
701    wincmd p
702    lnext
703    let fileName = expand("%")
704    wincmd p
705    let locationListFileName = substitute(getline(line('.')), '\([^|]*\)|.*', '\1', '')
706    let fileName = substitute(fileName, '\\', '/', 'g')
707    let locationListFileName = substitute(locationListFileName, '\\', '/', 'g')
708    call assert_equal("test://bar.txt", fileName)
709    call assert_equal("test://bar.txt", locationListFileName)
710
711    wincmd n | only
712
713    " Test B:
714    lrewind
715    lopen
716    2
717    exe "normal \<CR>"
718    wincmd p
719    3
720    exe "normal \<CR>"
721    wincmd p
722    4
723    exe "normal \<CR>"
724    call assert_equal(2, winnr('$'))
725    wincmd n | only
726
727    " Test C:
728    lrewind
729    lopen
730    " Let's move the location list window to the top to check whether it (the
731    " first window found) will be reused when we try to open new windows:
732    wincmd K
733    2
734    exe "normal \<CR>"
735    wincmd p
736    3
737    exe "normal \<CR>"
738    wincmd p
739    4
740    exe "normal \<CR>"
741    1wincmd w
742    call assert_equal('quickfix', &buftype)
743    2wincmd w
744    let bufferName = expand("%")
745    let bufferName = substitute(bufferName, '\\', '/', 'g')
746    call assert_equal('test://quux.txt', bufferName)
747
748    wincmd n | only
749
750    augroup! testgroup
751endfunc
752
753func Test_locationlist_curwin_was_closed()
754    augroup testgroup
755      au!
756      autocmd BufReadCmd test_curwin.txt call R(expand("<amatch>"))
757    augroup END
758
759    func! R(n)
760      quit
761    endfunc
762
763    new
764    let q = []
765    call add(q, {'filename': 'test_curwin.txt' })
766    call setloclist(0, q)
767    call assert_fails('lrewind', 'E924:')
768
769    augroup! testgroup
770endfunc
771
772func Test_locationlist_cross_tab_jump()
773  call writefile(['loclistfoo'], 'loclistfoo')
774  call writefile(['loclistbar'], 'loclistbar')
775  set switchbuf=usetab
776
777  edit loclistfoo
778  tabedit loclistbar
779  silent lgrep loclistfoo loclist*
780  call assert_equal(1, tabpagenr())
781
782  enew | only | tabonly
783  set switchbuf&vim
784  call delete('loclistfoo')
785  call delete('loclistbar')
786endfunc
787
788" More tests for 'errorformat'
789func Test_efm1()
790    if !has('unix')
791	" The 'errorformat' setting is different on non-Unix systems.
792	" This test works only on Unix-like systems.
793	return
794    endif
795
796    let l = [
797      \ '"Xtestfile", line 4.12: 1506-045 (S) Undeclared identifier fd_set.',
798      \ '"Xtestfile", line 6 col 19; this is an error',
799      \ 'gcc -c -DHAVE_CONFIsing-prototypes -I/usr/X11R6/include  version.c',
800      \ 'Xtestfile:9: parse error before `asd''',
801      \ 'make: *** [vim] Error 1',
802      \ 'in file "Xtestfile" linenr 10: there is an error',
803      \ '',
804      \ '2 returned',
805      \ '"Xtestfile", line 11 col 1; this is an error',
806      \ '"Xtestfile", line 12 col 2; this is another error',
807      \ '"Xtestfile", line 14:10; this is an error in column 10',
808      \ '=Xtestfile=, line 15:10; this is another error, but in vcol 10 this time',
809      \ '"Xtestfile", linenr 16: yet another problem',
810      \ 'Error in "Xtestfile" at line 17:',
811      \ 'x should be a dot',
812      \ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 17',
813      \ '            ^',
814      \ 'Error in "Xtestfile" at line 18:',
815      \ 'x should be a dot',
816      \ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 18',
817      \ '.............^',
818      \ 'Error in "Xtestfile" at line 19:',
819      \ 'x should be a dot',
820      \ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 19',
821      \ '--------------^',
822      \ 'Error in "Xtestfile" at line 20:',
823      \ 'x should be a dot',
824      \ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 20',
825      \ '	       ^',
826      \ '',
827      \ 'Does anyone know what is the problem and how to correction it?',
828      \ '"Xtestfile", line 21 col 9: What is the title of the quickfix window?',
829      \ '"Xtestfile", line 22 col 9: What is the title of the quickfix window?'
830      \ ]
831
832    call writefile(l, 'Xerrorfile1')
833    call writefile(l[:-2], 'Xerrorfile2')
834
835    let m = [
836	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  2',
837	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  3',
838	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  4',
839	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  5',
840	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  6',
841	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  7',
842	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  8',
843	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  9',
844	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 10',
845	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 11',
846	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 12',
847	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 13',
848	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 14',
849	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 15',
850	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 16',
851	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 17',
852	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 18',
853	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 19',
854	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 20',
855	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 21',
856	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 22'
857	\ ]
858    call writefile(m, 'Xtestfile')
859
860    let save_efm = &efm
861    set efm+==%f=\\,\ line\ %l%*\\D%v%*[^\ ]\ %m
862    set efm^=%AError\ in\ \"%f\"\ at\ line\ %l:,%Z%p^,%C%m
863
864    exe 'cf Xerrorfile2'
865    clast
866    copen
867    call assert_equal(':cf Xerrorfile2', w:quickfix_title)
868    wincmd p
869
870    exe 'cf Xerrorfile1'
871    call assert_equal([4, 12], [line('.'), col('.')])
872    cn
873    call assert_equal([6, 19], [line('.'), col('.')])
874    cn
875    call assert_equal([9, 2], [line('.'), col('.')])
876    cn
877    call assert_equal([10, 2], [line('.'), col('.')])
878    cn
879    call assert_equal([11, 1], [line('.'), col('.')])
880    cn
881    call assert_equal([12, 2], [line('.'), col('.')])
882    cn
883    call assert_equal([14, 10], [line('.'), col('.')])
884    cn
885    call assert_equal([15, 3, 10], [line('.'), col('.'), virtcol('.')])
886    cn
887    call assert_equal([16, 2], [line('.'), col('.')])
888    cn
889    call assert_equal([17, 6], [line('.'), col('.')])
890    cn
891    call assert_equal([18, 7], [line('.'), col('.')])
892    cn
893    call assert_equal([19, 8], [line('.'), col('.')])
894    cn
895    call assert_equal([20, 9], [line('.'), col('.')])
896    clast
897    cprev
898    cprev
899    wincmd w
900    call assert_equal(':cf Xerrorfile1', w:quickfix_title)
901    wincmd p
902
903    let &efm = save_efm
904    call delete('Xerrorfile1')
905    call delete('Xerrorfile2')
906    call delete('Xtestfile')
907endfunc
908
909" Test for quickfix directory stack support
910func s:dir_stack_tests(cchar)
911  call s:setup_commands(a:cchar)
912
913  let save_efm=&efm
914  set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f'
915
916  let lines = ["Entering dir 'dir1/a'",
917		\ 'habits2.txt:1:Nine Healthy Habits',
918		\ "Entering dir 'b'",
919		\ 'habits3.txt:2:0 Hours of television',
920		\ 'habits2.txt:7:5 Small meals',
921		\ "Entering dir 'dir1/c'",
922		\ 'habits4.txt:3:1 Hour of exercise',
923		\ "Leaving dir 'dir1/c'",
924		\ "Leaving dir 'dir1/a'",
925		\ 'habits1.txt:4:2 Liters of water',
926		\ "Entering dir 'dir2'",
927		\ 'habits5.txt:5:3 Cups of hot green tea',
928		\ "Leaving dir 'dir2'"
929		\]
930
931  Xexpr ""
932  for l in lines
933      Xaddexpr l
934  endfor
935
936  let qf = g:Xgetlist()
937
938  call assert_equal('dir1/a/habits2.txt', bufname(qf[1].bufnr))
939  call assert_equal(1, qf[1].lnum)
940  call assert_equal('dir1/a/b/habits3.txt', bufname(qf[3].bufnr))
941  call assert_equal(2, qf[3].lnum)
942  call assert_equal('dir1/a/habits2.txt', bufname(qf[4].bufnr))
943  call assert_equal(7, qf[4].lnum)
944  call assert_equal('dir1/c/habits4.txt', bufname(qf[6].bufnr))
945  call assert_equal(3, qf[6].lnum)
946  call assert_equal('habits1.txt', bufname(qf[9].bufnr))
947  call assert_equal(4, qf[9].lnum)
948  call assert_equal('dir2/habits5.txt', bufname(qf[11].bufnr))
949  call assert_equal(5, qf[11].lnum)
950
951  let &efm=save_efm
952endfunc
953
954" Tests for %D and %X errorformat options
955func Test_efm_dirstack()
956  " Create the directory stack and files
957  call mkdir('dir1')
958  call mkdir('dir1/a')
959  call mkdir('dir1/a/b')
960  call mkdir('dir1/c')
961  call mkdir('dir2')
962
963  let lines = ["Nine Healthy Habits",
964		\ "0 Hours of television",
965		\ "1 Hour of exercise",
966		\ "2 Liters of water",
967		\ "3 Cups of hot green tea",
968		\ "4 Short mental breaks",
969		\ "5 Small meals",
970		\ "6 AM wake up time",
971		\ "7 Minutes of laughter",
972		\ "8 Hours of sleep (at least)",
973		\ "9 PM end of the day and off to bed"
974		\ ]
975  call writefile(lines, 'habits1.txt')
976  call writefile(lines, 'dir1/a/habits2.txt')
977  call writefile(lines, 'dir1/a/b/habits3.txt')
978  call writefile(lines, 'dir1/c/habits4.txt')
979  call writefile(lines, 'dir2/habits5.txt')
980
981  call s:dir_stack_tests('c')
982  call s:dir_stack_tests('l')
983
984  call delete('dir1', 'rf')
985  call delete('dir2', 'rf')
986  call delete('habits1.txt')
987endfunc
988
989" Test for resync after continuing an ignored message
990func Xefm_ignore_continuations(cchar)
991  call s:setup_commands(a:cchar)
992
993  let save_efm = &efm
994
995  let &efm =
996	\ '%Eerror %m %l,' .
997	\ '%-Wignored %m %l,' .
998	\ '%+Cmore ignored %m %l,' .
999	\ '%Zignored end'
1000  Xgetexpr ['ignored warning 1', 'more ignored continuation 2', 'ignored end', 'error resync 4']
1001  let l = map(g:Xgetlist(), '[v:val.text, v:val.valid, v:val.lnum, v:val.type]')
1002  call assert_equal([['resync', 1, 4, 'E']], l)
1003
1004  let &efm = save_efm
1005endfunc
1006
1007func Test_efm_ignore_continuations()
1008  call Xefm_ignore_continuations('c')
1009  call Xefm_ignore_continuations('l')
1010endfunc
1011
1012" Tests for invalid error format specifies
1013func Xinvalid_efm_Tests(cchar)
1014  call s:setup_commands(a:cchar)
1015
1016  let save_efm = &efm
1017
1018  set efm=%f:%l:%m,%f:%f:%l:%m
1019  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E372:')
1020
1021  set efm=%f:%l:%m,%f:%l:%r:%m
1022  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E373:')
1023
1024  set efm=%f:%l:%m,%O:%f:%l:%m
1025  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E373:')
1026
1027  set efm=%f:%l:%m,%f:%l:%*[^a-z
1028  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E374:')
1029
1030  set efm=%f:%l:%m,%f:%l:%*c
1031  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E375:')
1032
1033  set efm=%f:%l:%m,%L%M%N
1034  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E376:')
1035
1036  set efm=%f:%l:%m,%f:%l:%m:%R
1037  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E377:')
1038
1039  set efm=
1040  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E378:')
1041
1042  set efm=%DEntering\ dir\ abc,%f:%l:%m
1043  call assert_fails('Xexpr ["Entering dir abc", "abc.txt:1:Hello world"]', 'E379:')
1044
1045  let &efm = save_efm
1046endfunc
1047
1048func Test_invalid_efm()
1049  call Xinvalid_efm_Tests('c')
1050  call Xinvalid_efm_Tests('l')
1051endfunc
1052
1053" TODO:
1054" Add tests for the following formats in 'errorformat'
1055"	%r  %O
1056func Test_efm2()
1057  let save_efm = &efm
1058
1059  " Test for %s format in efm
1060  set efm=%f:%s
1061  cexpr 'Xtestfile:Line search text'
1062  let l = getqflist()
1063  call assert_equal(l[0].pattern, '^\VLine search text\$')
1064  call assert_equal(l[0].lnum, 0)
1065
1066  let l = split(execute('clist', ''), "\n")
1067  call assert_equal([' 1 Xtestfile:^\VLine search text\$:  '], l)
1068
1069  " Test for %P, %Q and %t format specifiers
1070  let lines=["[Xtestfile1]",
1071	      \ "(1,17)  error: ';' missing",
1072	      \ "(21,2)  warning: variable 'z' not defined",
1073	      \ "(67,3)  error: end of file found before string ended",
1074	      \ "--",
1075	      \ "",
1076	      \ "[Xtestfile2]",
1077	      \ "--",
1078	      \ "",
1079	      \ "[Xtestfile3]",
1080	      \ "NEW compiler v1.1",
1081	      \ "(2,2)   warning: variable 'x' not defined",
1082	      \ "(67,3)  warning: 's' already defined",
1083	      \ "--"
1084	      \]
1085  set efm=%+P[%f]%r,(%l\\,%c)%*[\ ]%t%*[^:]:\ %m,%+Q--%r
1086  " To exercise the push/pop file functionality in quickfix, the test files
1087  " need to be created.
1088  call writefile(['Line1'], 'Xtestfile1')
1089  call writefile(['Line2'], 'Xtestfile2')
1090  call writefile(['Line3'], 'Xtestfile3')
1091  cexpr ""
1092  for l in lines
1093      caddexpr l
1094  endfor
1095  let l = getqflist()
1096  call assert_equal(12, len(l))
1097  call assert_equal(21, l[2].lnum)
1098  call assert_equal(2, l[2].col)
1099  call assert_equal('w', l[2].type)
1100  call assert_equal('e', l[3].type)
1101  call delete('Xtestfile1')
1102  call delete('Xtestfile2')
1103  call delete('Xtestfile3')
1104
1105  " Tests for %E, %C and %Z format specifiers
1106  let lines = ["Error 275",
1107	      \ "line 42",
1108	      \ "column 3",
1109	      \ "' ' expected after '--'"
1110	      \]
1111  set efm=%EError\ %n,%Cline\ %l,%Ccolumn\ %c,%Z%m
1112  cgetexpr lines
1113  let l = getqflist()
1114  call assert_equal(275, l[0].nr)
1115  call assert_equal(42, l[0].lnum)
1116  call assert_equal(3, l[0].col)
1117  call assert_equal('E', l[0].type)
1118  call assert_equal("\n' ' expected after '--'", l[0].text)
1119
1120  " Test for %>
1121  let lines = ["Error in line 147 of foo.c:",
1122	      \"unknown variable 'i'"
1123	      \]
1124  set efm=unknown\ variable\ %m,%E%>Error\ in\ line\ %l\ of\ %f:,%Z%m
1125  cgetexpr lines
1126  let l = getqflist()
1127  call assert_equal(147, l[0].lnum)
1128  call assert_equal('E', l[0].type)
1129  call assert_equal("\nunknown variable 'i'", l[0].text)
1130
1131  " Test for %A, %C and other formats
1132  let lines = [
1133	  \"==============================================================",
1134	  \"FAIL: testGetTypeIdCachesResult (dbfacadeTest.DjsDBFacadeTest)",
1135	  \"--------------------------------------------------------------",
1136	  \"Traceback (most recent call last):",
1137	  \'  File "unittests/dbfacadeTest.py", line 89, in testFoo',
1138	  \"    self.assertEquals(34, dtid)",
1139	  \'  File "/usr/lib/python2.2/unittest.py", line 286, in',
1140	  \" failUnlessEqual",
1141	  \"    raise self.failureException, \\",
1142	  \"AssertionError: 34 != 33",
1143	  \"",
1144	  \"--------------------------------------------------------------",
1145	  \"Ran 27 tests in 0.063s"
1146	  \]
1147  set efm=%C\ %.%#,%A\ \ File\ \"%f\"\\,\ line\ %l%.%#,%Z%[%^\ ]%\\@=%m
1148  cgetexpr lines
1149  let l = getqflist()
1150  call assert_equal(8, len(l))
1151  call assert_equal(89, l[4].lnum)
1152  call assert_equal(1, l[4].valid)
1153  call assert_equal('unittests/dbfacadeTest.py', bufname(l[4].bufnr))
1154
1155  " Test for %o
1156  set efm=%f(%o):%l\ %m
1157  cgetexpr ['Xotestfile(Language.PureScript.Types):20 Error']
1158  call writefile(['Line1'], 'Xotestfile')
1159  let l = getqflist()
1160  call assert_equal(1, len(l), string(l))
1161  call assert_equal('Language.PureScript.Types', l[0].module)
1162  copen
1163  call assert_equal('Language.PureScript.Types|20| Error', getline(1))
1164  call feedkeys("\<CR>", 'xn')
1165  call assert_equal('Xotestfile', expand('%:t'))
1166  cclose
1167  bd
1168  call delete("Xotestfile")
1169
1170  " The following sequence of commands used to crash Vim
1171  set efm=%W%m
1172  cgetexpr ['msg1']
1173  let l = getqflist()
1174  call assert_equal(1, len(l), string(l))
1175  call assert_equal('msg1', l[0].text)
1176  set efm=%C%m
1177  lexpr 'msg2'
1178  let l = getloclist(0)
1179  call assert_equal(1, len(l), string(l))
1180  call assert_equal('msg2', l[0].text)
1181  lopen
1182  call setqflist([], 'r')
1183  caddbuf
1184  let l = getqflist()
1185  call assert_equal(1, len(l), string(l))
1186  call assert_equal('|| msg2', l[0].text)
1187
1188  new | only
1189  let &efm = save_efm
1190endfunc
1191
1192func XquickfixChangedByAutocmd(cchar)
1193  call s:setup_commands(a:cchar)
1194  if a:cchar == 'c'
1195    let ErrorNr = 'E925'
1196    func! ReadFunc()
1197      colder
1198      cgetexpr []
1199    endfunc
1200  else
1201    let ErrorNr = 'E926'
1202    func! ReadFunc()
1203      lolder
1204      lgetexpr []
1205    endfunc
1206  endif
1207
1208  augroup testgroup
1209    au!
1210    autocmd BufReadCmd test_changed.txt call ReadFunc()
1211  augroup END
1212
1213  new | only
1214  let words = [ "a", "b" ]
1215  let qflist = []
1216  for word in words
1217    call add(qflist, {'filename': 'test_changed.txt'})
1218    call g:Xsetlist(qflist, ' ')
1219  endfor
1220  call assert_fails('Xrewind', ErrorNr . ':')
1221
1222  augroup! testgroup
1223endfunc
1224
1225func Test_quickfix_was_changed_by_autocmd()
1226  call XquickfixChangedByAutocmd('c')
1227  call XquickfixChangedByAutocmd('l')
1228endfunc
1229
1230func Test_caddbuffer_to_empty()
1231  helpgr quickfix
1232  call setqflist([], 'r')
1233  cad
1234  try
1235    cn
1236  catch
1237    " number of matches is unknown
1238    call assert_true(v:exception =~ 'E553:')
1239  endtry
1240  quit!
1241endfunc
1242
1243func Test_cgetexpr_works()
1244  " this must not crash Vim
1245  cgetexpr [$x]
1246  lgetexpr [$x]
1247endfunc
1248
1249" Tests for the setqflist() and setloclist() functions
1250func SetXlistTests(cchar, bnum)
1251  call s:setup_commands(a:cchar)
1252
1253  call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 1},
1254	      \  {'bufnr': a:bnum, 'lnum': 2}])
1255  let l = g:Xgetlist()
1256  call assert_equal(2, len(l))
1257  call assert_equal(2, l[1].lnum)
1258
1259  Xnext
1260  call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 3}], 'a')
1261  let l = g:Xgetlist()
1262  call assert_equal(3, len(l))
1263  Xnext
1264  call assert_equal(3, line('.'))
1265
1266  " Appending entries to the list should not change the cursor position
1267  " in the quickfix window
1268  Xwindow
1269  1
1270  call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 4},
1271	      \  {'bufnr': a:bnum, 'lnum': 5}], 'a')
1272  call assert_equal(1, line('.'))
1273  close
1274
1275  call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 3},
1276	      \  {'bufnr': a:bnum, 'lnum': 4},
1277	      \  {'bufnr': a:bnum, 'lnum': 5}], 'r')
1278  let l = g:Xgetlist()
1279  call assert_equal(3, len(l))
1280  call assert_equal(5, l[2].lnum)
1281
1282  call g:Xsetlist([])
1283  let l = g:Xgetlist()
1284  call assert_equal(0, len(l))
1285
1286  " Tests for setting the 'valid' flag
1287  call g:Xsetlist([{'bufnr':a:bnum, 'lnum':4, 'valid':0}])
1288  Xwindow
1289  call assert_equal(1, winnr('$'))
1290  let l = g:Xgetlist()
1291  call g:Xsetlist(l)
1292  call assert_equal(0, g:Xgetlist()[0].valid)
1293  call g:Xsetlist([{'text':'Text1', 'valid':1}])
1294  Xwindow
1295  call assert_equal(2, winnr('$'))
1296  Xclose
1297  let save_efm = &efm
1298  set efm=%m
1299  Xgetexpr 'TestMessage'
1300  let l = g:Xgetlist()
1301  call g:Xsetlist(l)
1302  call assert_equal(1, g:Xgetlist()[0].valid)
1303  let &efm = save_efm
1304
1305  " Error cases:
1306  " Refer to a non-existing buffer and pass a non-dictionary type
1307  call assert_fails("call g:Xsetlist([{'bufnr':998, 'lnum':4}," .
1308	      \ " {'bufnr':999, 'lnum':5}])", 'E92:')
1309  call g:Xsetlist([[1, 2,3]])
1310  call assert_equal(0, len(g:Xgetlist()))
1311endfunc
1312
1313func Test_setqflist()
1314  new Xtestfile | only
1315  let bnum = bufnr('%')
1316  call setline(1, range(1,5))
1317
1318  call SetXlistTests('c', bnum)
1319  call SetXlistTests('l', bnum)
1320
1321  enew!
1322  call delete('Xtestfile')
1323endfunc
1324
1325func Xlist_empty_middle(cchar)
1326  call s:setup_commands(a:cchar)
1327
1328  " create three quickfix lists
1329  let @/ = 'Test_'
1330  Xvimgrep // test_quickfix.vim
1331  let testlen = len(g:Xgetlist())
1332  call assert_true(testlen > 0)
1333  Xvimgrep empty test_quickfix.vim
1334  call assert_true(len(g:Xgetlist()) > 0)
1335  Xvimgrep matches test_quickfix.vim
1336  let matchlen = len(g:Xgetlist())
1337  call assert_true(matchlen > 0)
1338  Xolder
1339  " make the middle list empty
1340  call g:Xsetlist([], 'r')
1341  call assert_true(len(g:Xgetlist()) == 0)
1342  Xolder
1343  call assert_equal(testlen, len(g:Xgetlist()))
1344  Xnewer
1345  Xnewer
1346  call assert_equal(matchlen, len(g:Xgetlist()))
1347endfunc
1348
1349func Test_setqflist_empty_middle()
1350  call Xlist_empty_middle('c')
1351  call Xlist_empty_middle('l')
1352endfunc
1353
1354func Xlist_empty_older(cchar)
1355  call s:setup_commands(a:cchar)
1356
1357  " create three quickfix lists
1358  Xvimgrep one test_quickfix.vim
1359  let onelen = len(g:Xgetlist())
1360  call assert_true(onelen > 0)
1361  Xvimgrep two test_quickfix.vim
1362  let twolen = len(g:Xgetlist())
1363  call assert_true(twolen > 0)
1364  Xvimgrep three test_quickfix.vim
1365  let threelen = len(g:Xgetlist())
1366  call assert_true(threelen > 0)
1367  Xolder 2
1368  " make the first list empty, check the others didn't change
1369  call g:Xsetlist([], 'r')
1370  call assert_true(len(g:Xgetlist()) == 0)
1371  Xnewer
1372  call assert_equal(twolen, len(g:Xgetlist()))
1373  Xnewer
1374  call assert_equal(threelen, len(g:Xgetlist()))
1375endfunc
1376
1377func Test_setqflist_empty_older()
1378  call Xlist_empty_older('c')
1379  call Xlist_empty_older('l')
1380endfunc
1381
1382func XquickfixSetListWithAct(cchar)
1383  call s:setup_commands(a:cchar)
1384
1385  let list1 = [{'filename': 'fnameA', 'text': 'A'},
1386          \    {'filename': 'fnameB', 'text': 'B'}]
1387  let list2 = [{'filename': 'fnameC', 'text': 'C'},
1388          \    {'filename': 'fnameD', 'text': 'D'},
1389          \    {'filename': 'fnameE', 'text': 'E'}]
1390
1391  " {action} is unspecified.  Same as specifing ' '.
1392  new | only
1393  silent! Xnewer 99
1394  call g:Xsetlist(list1)
1395  call g:Xsetlist(list2)
1396  let li = g:Xgetlist()
1397  call assert_equal(3, len(li))
1398  call assert_equal('C', li[0]['text'])
1399  call assert_equal('D', li[1]['text'])
1400  call assert_equal('E', li[2]['text'])
1401  silent! Xolder
1402  let li = g:Xgetlist()
1403  call assert_equal(2, len(li))
1404  call assert_equal('A', li[0]['text'])
1405  call assert_equal('B', li[1]['text'])
1406
1407  " {action} is specified ' '.
1408  new | only
1409  silent! Xnewer 99
1410  call g:Xsetlist(list1)
1411  call g:Xsetlist(list2, ' ')
1412  let li = g:Xgetlist()
1413  call assert_equal(3, len(li))
1414  call assert_equal('C', li[0]['text'])
1415  call assert_equal('D', li[1]['text'])
1416  call assert_equal('E', li[2]['text'])
1417  silent! Xolder
1418  let li = g:Xgetlist()
1419  call assert_equal(2, len(li))
1420  call assert_equal('A', li[0]['text'])
1421  call assert_equal('B', li[1]['text'])
1422
1423  " {action} is specified 'a'.
1424  new | only
1425  silent! Xnewer 99
1426  call g:Xsetlist(list1)
1427  call g:Xsetlist(list2, 'a')
1428  let li = g:Xgetlist()
1429  call assert_equal(5, len(li))
1430  call assert_equal('A', li[0]['text'])
1431  call assert_equal('B', li[1]['text'])
1432  call assert_equal('C', li[2]['text'])
1433  call assert_equal('D', li[3]['text'])
1434  call assert_equal('E', li[4]['text'])
1435
1436  " {action} is specified 'r'.
1437  new | only
1438  silent! Xnewer 99
1439  call g:Xsetlist(list1)
1440  call g:Xsetlist(list2, 'r')
1441  let li = g:Xgetlist()
1442  call assert_equal(3, len(li))
1443  call assert_equal('C', li[0]['text'])
1444  call assert_equal('D', li[1]['text'])
1445  call assert_equal('E', li[2]['text'])
1446
1447  " Test for wrong value.
1448  new | only
1449  call assert_fails("call g:Xsetlist(0)", 'E714:')
1450  call assert_fails("call g:Xsetlist(list1, '')", 'E927:')
1451  call assert_fails("call g:Xsetlist(list1, 'aa')", 'E927:')
1452  call assert_fails("call g:Xsetlist(list1, ' a')", 'E927:')
1453  call assert_fails("call g:Xsetlist(list1, 0)", 'E928:')
1454endfunc
1455
1456func Test_setqflist_invalid_nr()
1457  " The following command used to crash Vim
1458  call setqflist([], ' ', {'nr' : $XXX_DOES_NOT_EXIST})
1459endfunc
1460
1461func Test_quickfix_set_list_with_act()
1462  call XquickfixSetListWithAct('c')
1463  call XquickfixSetListWithAct('l')
1464endfunc
1465
1466func XLongLinesTests(cchar)
1467  let l = g:Xgetlist()
1468
1469  call assert_equal(4, len(l))
1470  call assert_equal(1, l[0].lnum)
1471  call assert_equal(1, l[0].col)
1472  call assert_equal(1975, len(l[0].text))
1473  call assert_equal(2, l[1].lnum)
1474  call assert_equal(1, l[1].col)
1475  call assert_equal(4070, len(l[1].text))
1476  call assert_equal(3, l[2].lnum)
1477  call assert_equal(1, l[2].col)
1478  call assert_equal(4070, len(l[2].text))
1479  call assert_equal(4, l[3].lnum)
1480  call assert_equal(1, l[3].col)
1481  call assert_equal(10, len(l[3].text))
1482
1483  call g:Xsetlist([], 'r')
1484endfunc
1485
1486func s:long_lines_tests(cchar)
1487  call s:setup_commands(a:cchar)
1488
1489  let testfile = 'samples/quickfix.txt'
1490
1491  " file
1492  exe 'Xgetfile' testfile
1493  call XLongLinesTests(a:cchar)
1494
1495  " list
1496  Xexpr readfile(testfile)
1497  call XLongLinesTests(a:cchar)
1498
1499  " string
1500  Xexpr join(readfile(testfile), "\n")
1501  call XLongLinesTests(a:cchar)
1502
1503  " buffer
1504  exe 'edit' testfile
1505  exe 'Xbuffer' bufnr('%')
1506  call XLongLinesTests(a:cchar)
1507endfunc
1508
1509func Test_long_lines()
1510  call s:long_lines_tests('c')
1511  call s:long_lines_tests('l')
1512endfunc
1513
1514func s:create_test_file(filename)
1515  let l = []
1516  for i in range(1, 20)
1517      call add(l, 'Line' . i)
1518  endfor
1519  call writefile(l, a:filename)
1520endfunc
1521
1522func Test_switchbuf()
1523  call s:create_test_file('Xqftestfile1')
1524  call s:create_test_file('Xqftestfile2')
1525  call s:create_test_file('Xqftestfile3')
1526
1527  new | only
1528  edit Xqftestfile1
1529  let file1_winid = win_getid()
1530  new Xqftestfile2
1531  let file2_winid = win_getid()
1532  cgetexpr ['Xqftestfile1:5:Line5',
1533		\ 'Xqftestfile1:6:Line6',
1534		\ 'Xqftestfile2:10:Line10',
1535		\ 'Xqftestfile2:11:Line11',
1536		\ 'Xqftestfile3:15:Line15',
1537		\ 'Xqftestfile3:16:Line16']
1538
1539  new
1540  let winid = win_getid()
1541  cfirst | cnext
1542  call assert_equal(winid, win_getid())
1543  2cnext
1544  call assert_equal(winid, win_getid())
1545  2cnext
1546  call assert_equal(winid, win_getid())
1547  enew
1548
1549  set switchbuf=useopen
1550  cfirst | cnext
1551  call assert_equal(file1_winid, win_getid())
1552  2cnext
1553  call assert_equal(file2_winid, win_getid())
1554  2cnext
1555  call assert_equal(file2_winid, win_getid())
1556
1557  enew | only
1558  set switchbuf=usetab
1559  tabedit Xqftestfile1
1560  tabedit Xqftestfile2
1561  tabedit Xqftestfile3
1562  tabfirst
1563  cfirst | cnext
1564  call assert_equal(2, tabpagenr())
1565  2cnext
1566  call assert_equal(3, tabpagenr())
1567  6cnext
1568  call assert_equal(4, tabpagenr())
1569  2cpfile
1570  call assert_equal(2, tabpagenr())
1571  2cnfile
1572  call assert_equal(4, tabpagenr())
1573  tabfirst | tabonly | enew
1574
1575  set switchbuf=split
1576  cfirst | cnext
1577  call assert_equal(1, winnr('$'))
1578  cnext | cnext
1579  call assert_equal(2, winnr('$'))
1580  cnext | cnext
1581  call assert_equal(3, winnr('$'))
1582  enew | only
1583
1584  set switchbuf=newtab
1585  cfirst | cnext
1586  call assert_equal(1, tabpagenr('$'))
1587  cnext | cnext
1588  call assert_equal(2, tabpagenr('$'))
1589  cnext | cnext
1590  call assert_equal(3, tabpagenr('$'))
1591  tabfirst | enew | tabonly | only
1592
1593  set switchbuf=
1594  edit Xqftestfile1
1595  let file1_winid = win_getid()
1596  new Xqftestfile2
1597  let file2_winid = win_getid()
1598  copen
1599  exe "normal 1G\<CR>"
1600  call assert_equal(file1_winid, win_getid())
1601  copen
1602  exe "normal 3G\<CR>"
1603  call assert_equal(file2_winid, win_getid())
1604  copen | only
1605  exe "normal 5G\<CR>"
1606  call assert_equal(2, winnr('$'))
1607  call assert_equal(1, bufwinnr('Xqftestfile3'))
1608
1609  " If only quickfix window is open in the current tabpage, jumping to an
1610  " entry with 'switchubf' set to 'usetab' should search in other tabpages.
1611  enew | only
1612  set switchbuf=usetab
1613  tabedit Xqftestfile1
1614  tabedit Xqftestfile2
1615  tabedit Xqftestfile3
1616  tabfirst
1617  copen | only
1618  clast
1619  call assert_equal(4, tabpagenr())
1620  tabfirst | tabonly | enew | only
1621
1622  call delete('Xqftestfile1')
1623  call delete('Xqftestfile2')
1624  call delete('Xqftestfile3')
1625  set switchbuf&vim
1626
1627  enew | only
1628endfunc
1629
1630func Xadjust_qflnum(cchar)
1631  call s:setup_commands(a:cchar)
1632
1633  enew | only
1634
1635  let fname = 'Xqftestfile' . a:cchar
1636  call s:create_test_file(fname)
1637  exe 'edit ' . fname
1638
1639  Xgetexpr [fname . ':5:Line5',
1640	      \ fname . ':10:Line10',
1641	      \ fname . ':15:Line15',
1642	      \ fname . ':20:Line20']
1643
1644  6,14delete
1645  call append(6, ['Buffer', 'Window'])
1646
1647  let l = g:Xgetlist()
1648
1649  call assert_equal(5, l[0].lnum)
1650  call assert_equal(6, l[2].lnum)
1651  call assert_equal(13, l[3].lnum)
1652
1653  enew!
1654  call delete(fname)
1655endfunc
1656
1657func Test_adjust_lnum()
1658  call setloclist(0, [])
1659  call Xadjust_qflnum('c')
1660  call setqflist([])
1661  call Xadjust_qflnum('l')
1662endfunc
1663
1664" Tests for the :grep/:lgrep and :grepadd/:lgrepadd commands
1665func s:test_xgrep(cchar)
1666  call s:setup_commands(a:cchar)
1667
1668  " The following lines are used for the grep test. Don't remove.
1669  " Grep_Test_Text: Match 1
1670  " Grep_Test_Text: Match 2
1671  " GrepAdd_Test_Text: Match 1
1672  " GrepAdd_Test_Text: Match 2
1673  enew! | only
1674  set makeef&vim
1675  silent Xgrep Grep_Test_Text: test_quickfix.vim
1676  call assert_true(len(g:Xgetlist()) == 3)
1677  Xopen
1678  call assert_true(w:quickfix_title =~ '^:grep')
1679  Xclose
1680  enew
1681  set makeef=Temp_File_##
1682  silent Xgrepadd GrepAdd_Test_Text: test_quickfix.vim
1683  call assert_true(len(g:Xgetlist()) == 6)
1684endfunc
1685
1686func Test_grep()
1687  if !has('unix')
1688    " The grepprg may not be set on non-Unix systems
1689    return
1690  endif
1691
1692  call s:test_xgrep('c')
1693  call s:test_xgrep('l')
1694endfunc
1695
1696func Test_two_windows()
1697  " Use one 'errorformat' for two windows.  Add an expression to each of them,
1698  " make sure they each keep their own state.
1699  set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f'
1700  call mkdir('Xone/a', 'p')
1701  call mkdir('Xtwo/a', 'p')
1702  let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7']
1703  call writefile(lines, 'Xone/a/one.txt')
1704  call writefile(lines, 'Xtwo/a/two.txt')
1705
1706  new one
1707  let one_id = win_getid()
1708  lexpr ""
1709  new two
1710  let two_id = win_getid()
1711  lexpr ""
1712
1713  laddexpr "Entering dir 'Xtwo/a'"
1714  call win_gotoid(one_id)
1715  laddexpr "Entering dir 'Xone/a'"
1716  call win_gotoid(two_id)
1717  laddexpr 'two.txt:5:two two two'
1718  call win_gotoid(one_id)
1719  laddexpr 'one.txt:3:one one one'
1720
1721  let loc_one = getloclist(one_id)
1722  call assert_equal('Xone/a/one.txt', bufname(loc_one[1].bufnr))
1723  call assert_equal(3, loc_one[1].lnum)
1724
1725  let loc_two = getloclist(two_id)
1726  call assert_equal('Xtwo/a/two.txt', bufname(loc_two[1].bufnr))
1727  call assert_equal(5, loc_two[1].lnum)
1728
1729  call win_gotoid(one_id)
1730  bwipe!
1731  call win_gotoid(two_id)
1732  bwipe!
1733  call delete('Xone', 'rf')
1734  call delete('Xtwo', 'rf')
1735endfunc
1736
1737func XbottomTests(cchar)
1738  call s:setup_commands(a:cchar)
1739
1740  " Calling lbottom without any errors should fail
1741  if a:cchar == 'l'
1742      call assert_fails('lbottom', 'E776:')
1743  endif
1744
1745  call g:Xsetlist([{'filename': 'foo', 'lnum': 42}])
1746  Xopen
1747  let wid = win_getid()
1748  call assert_equal(1, line('.'))
1749  wincmd w
1750  call g:Xsetlist([{'filename': 'var', 'lnum': 24}], 'a')
1751  Xbottom
1752  call win_gotoid(wid)
1753  call assert_equal(2, line('.'))
1754  Xclose
1755endfunc
1756
1757" Tests for the :cbottom and :lbottom commands
1758func Test_cbottom()
1759  call XbottomTests('c')
1760  call XbottomTests('l')
1761endfunc
1762
1763func HistoryTest(cchar)
1764  call s:setup_commands(a:cchar)
1765
1766  " clear all lists after the first one, then replace the first one.
1767  call g:Xsetlist([])
1768  call assert_fails('Xolder 99', 'E380:')
1769  let entry = {'filename': 'foo', 'lnum': 42}
1770  call g:Xsetlist([entry], 'r')
1771  call g:Xsetlist([entry, entry])
1772  call g:Xsetlist([entry, entry, entry])
1773  let res = split(execute(a:cchar . 'hist'), "\n")
1774  call assert_equal(3, len(res))
1775  let common = 'errors     :set' . (a:cchar == 'c' ? 'qf' : 'loc') . 'list()'
1776  call assert_equal('  error list 1 of 3; 1 ' . common, res[0])
1777  call assert_equal('  error list 2 of 3; 2 ' . common, res[1])
1778  call assert_equal('> error list 3 of 3; 3 ' . common, res[2])
1779
1780  call g:Xsetlist([], 'f')
1781  let l = split(execute(a:cchar . 'hist'), "\n")
1782  call assert_equal('No entries', l[0])
1783endfunc
1784
1785func Test_history()
1786  call HistoryTest('c')
1787  call HistoryTest('l')
1788endfunc
1789
1790func Test_duplicate_buf()
1791  " make sure we can get the highest buffer number
1792  edit DoesNotExist
1793  edit DoesNotExist2
1794  let last_buffer = bufnr("$")
1795
1796  " make sure only one buffer is created
1797  call writefile(['this one', 'that one'], 'Xgrepthis')
1798  vimgrep one Xgrepthis
1799  vimgrep one Xgrepthis
1800  call assert_equal(last_buffer + 1, bufnr("$"))
1801
1802  call delete('Xgrepthis')
1803endfunc
1804
1805" Quickfix/Location list set/get properties tests
1806func Xproperty_tests(cchar)
1807    call s:setup_commands(a:cchar)
1808
1809    " Error cases
1810    call assert_fails('call g:Xgetlist(99)', 'E715:')
1811    call assert_fails('call g:Xsetlist(99)', 'E714:')
1812    call assert_fails('call g:Xsetlist([], "a", [])', 'E715:')
1813
1814    " Set and get the title
1815    call g:Xsetlist([])
1816    Xopen
1817    wincmd p
1818    call g:Xsetlist([{'filename':'foo', 'lnum':27}])
1819    let s = g:Xsetlist([], 'a', {'title' : 'Sample'})
1820    call assert_equal(0, s)
1821    let d = g:Xgetlist({"title":1})
1822    call assert_equal('Sample', d.title)
1823    " Try setting title to a non-string value
1824    call assert_equal(-1, g:Xsetlist([], 'a', {'title' : ['Test']}))
1825    call assert_equal('Sample', g:Xgetlist({"title":1}).title)
1826
1827    Xopen
1828    call assert_equal('Sample', w:quickfix_title)
1829    Xclose
1830
1831    " Tests for action argument
1832    silent! Xolder 999
1833    let qfnr = g:Xgetlist({'all':1}).nr
1834    call g:Xsetlist([], 'r', {'title' : 'N1'})
1835    call assert_equal('N1', g:Xgetlist({'all':1}).title)
1836    call g:Xsetlist([], ' ', {'title' : 'N2'})
1837    call assert_equal(qfnr + 1, g:Xgetlist({'all':1}).nr)
1838
1839    let res = g:Xgetlist({'nr': 0})
1840    call assert_equal(qfnr + 1, res.nr)
1841    call assert_equal(['nr'], keys(res))
1842
1843    call g:Xsetlist([], ' ', {'title' : 'N3'})
1844    call assert_equal('N2', g:Xgetlist({'nr':2, 'title':1}).title)
1845
1846    " Changing the title of an earlier quickfix list
1847    call g:Xsetlist([], 'r', {'title' : 'NewTitle', 'nr' : 2})
1848    call assert_equal('NewTitle', g:Xgetlist({'nr':2, 'title':1}).title)
1849
1850    " Changing the title of an invalid quickfix list
1851    call assert_equal(-1, g:Xsetlist([], ' ',
1852		\ {'title' : 'SomeTitle', 'nr' : 99}))
1853    call assert_equal(-1, g:Xsetlist([], ' ',
1854		\ {'title' : 'SomeTitle', 'nr' : 'abc'}))
1855
1856    if a:cchar == 'c'
1857	copen
1858	call assert_equal({'winid':win_getid()}, getqflist({'winid':1}))
1859	cclose
1860    endif
1861
1862    " Invalid arguments
1863    call assert_fails('call g:Xgetlist([])', 'E715')
1864    call assert_fails('call g:Xsetlist([], "a", [])', 'E715')
1865    let s = g:Xsetlist([], 'a', {'abc':1})
1866    call assert_equal(-1, s)
1867
1868    call assert_equal({}, g:Xgetlist({'abc':1}))
1869    call assert_equal('', g:Xgetlist({'nr':99, 'title':1}).title)
1870    call assert_equal('', g:Xgetlist({'nr':[], 'title':1}).title)
1871
1872    if a:cchar == 'l'
1873	call assert_equal({}, getloclist(99, {'title': 1}))
1874    endif
1875
1876    " Context related tests
1877    let s = g:Xsetlist([], 'a', {'context':[1,2,3]})
1878    call assert_equal(0, s)
1879    call test_garbagecollect_now()
1880    let d = g:Xgetlist({'context':1})
1881    call assert_equal([1,2,3], d.context)
1882    call g:Xsetlist([], 'a', {'context':{'color':'green'}})
1883    let d = g:Xgetlist({'context':1})
1884    call assert_equal({'color':'green'}, d.context)
1885    call g:Xsetlist([], 'a', {'context':"Context info"})
1886    let d = g:Xgetlist({'context':1})
1887    call assert_equal("Context info", d.context)
1888    call g:Xsetlist([], 'a', {'context':246})
1889    let d = g:Xgetlist({'context':1})
1890    call assert_equal(246, d.context)
1891    if a:cchar == 'l'
1892	" Test for copying context across two different location lists
1893	new | only
1894	let w1_id = win_getid()
1895	let l = [1]
1896	call setloclist(0, [], 'a', {'context':l})
1897	new
1898	let w2_id = win_getid()
1899	call add(l, 2)
1900	call assert_equal([1, 2], getloclist(w1_id, {'context':1}).context)
1901	call assert_equal([1, 2], getloclist(w2_id, {'context':1}).context)
1902	unlet! l
1903	call assert_equal([1, 2], getloclist(w2_id, {'context':1}).context)
1904	only
1905	call setloclist(0, [], 'f')
1906	call assert_equal('', getloclist(0, {'context':1}).context)
1907    endif
1908
1909    " Test for changing the context of previous quickfix lists
1910    call g:Xsetlist([], 'f')
1911    Xexpr "One"
1912    Xexpr "Two"
1913    Xexpr "Three"
1914    call g:Xsetlist([], 'r', {'context' : [1], 'nr' : 1})
1915    call g:Xsetlist([], 'a', {'context' : [2], 'nr' : 2})
1916    " Also, check for setting the context using quickfix list number zero.
1917    call g:Xsetlist([], 'r', {'context' : [3], 'nr' : 0})
1918    call test_garbagecollect_now()
1919    let l = g:Xgetlist({'nr' : 1, 'context' : 1})
1920    call assert_equal([1], l.context)
1921    let l = g:Xgetlist({'nr' : 2, 'context' : 1})
1922    call assert_equal([2], l.context)
1923    let l = g:Xgetlist({'nr' : 3, 'context' : 1})
1924    call assert_equal([3], l.context)
1925
1926    " Test for changing the context through reference and for garbage
1927    " collection of quickfix context
1928    let l = ["red"]
1929    call g:Xsetlist([], ' ', {'context' : l})
1930    call add(l, "blue")
1931    let x = g:Xgetlist({'context' : 1})
1932    call add(x.context, "green")
1933    call assert_equal(["red", "blue", "green"], l)
1934    call assert_equal(["red", "blue", "green"], x.context)
1935    unlet l
1936    call test_garbagecollect_now()
1937    let m = g:Xgetlist({'context' : 1})
1938    call assert_equal(["red", "blue", "green"], m.context)
1939
1940    " Test for setting/getting items
1941    Xexpr ""
1942    let qfprev = g:Xgetlist({'nr':0})
1943    let s = g:Xsetlist([], ' ', {'title':'Green',
1944		\ 'items' : [{'filename':'F1', 'lnum':10}]})
1945    call assert_equal(0, s)
1946    let qfcur = g:Xgetlist({'nr':0})
1947    call assert_true(qfcur.nr == qfprev.nr + 1)
1948    let l = g:Xgetlist({'items':1})
1949    call assert_equal('F1', bufname(l.items[0].bufnr))
1950    call assert_equal(10, l.items[0].lnum)
1951    call g:Xsetlist([], 'a', {'items' : [{'filename':'F2', 'lnum':20},
1952		\  {'filename':'F2', 'lnum':30}]})
1953    let l = g:Xgetlist({'items':1})
1954    call assert_equal('F2', bufname(l.items[2].bufnr))
1955    call assert_equal(30, l.items[2].lnum)
1956    call g:Xsetlist([], 'r', {'items' : [{'filename':'F3', 'lnum':40}]})
1957    let l = g:Xgetlist({'items':1})
1958    call assert_equal('F3', bufname(l.items[0].bufnr))
1959    call assert_equal(40, l.items[0].lnum)
1960    call g:Xsetlist([], 'r', {'items' : []})
1961    let l = g:Xgetlist({'items':1})
1962    call assert_equal(0, len(l.items))
1963
1964    call g:Xsetlist([], 'r', {'title' : 'TestTitle'})
1965    call g:Xsetlist([], 'r', {'items' : [{'filename' : 'F1', 'lnum' : 10, 'text' : 'L10'}]})
1966    call g:Xsetlist([], 'r', {'items' : [{'filename' : 'F1', 'lnum' : 10, 'text' : 'L10'}]})
1967    call assert_equal('TestTitle', g:Xgetlist({'title' : 1}).title)
1968
1969    " The following used to crash Vim with address sanitizer
1970    call g:Xsetlist([], 'f')
1971    call g:Xsetlist([], 'a', {'items' : [{'filename':'F1', 'lnum':10}]})
1972    call assert_equal(10, g:Xgetlist({'items':1}).items[0].lnum)
1973
1974    " Try setting the items using a string
1975    call assert_equal(-1, g:Xsetlist([], ' ', {'items' : 'Test'}))
1976
1977    " Save and restore the quickfix stack
1978    call g:Xsetlist([], 'f')
1979    call assert_equal(0, g:Xgetlist({'nr':'$'}).nr)
1980    Xexpr "File1:10:Line1"
1981    Xexpr "File2:20:Line2"
1982    Xexpr "File3:30:Line3"
1983    let last_qf = g:Xgetlist({'nr':'$'}).nr
1984    call assert_equal(3, last_qf)
1985    let qstack = []
1986    for i in range(1, last_qf)
1987	let qstack = add(qstack, g:Xgetlist({'nr':i, 'all':1}))
1988    endfor
1989    call g:Xsetlist([], 'f')
1990    for i in range(len(qstack))
1991	call g:Xsetlist([], ' ', qstack[i])
1992    endfor
1993    call assert_equal(3, g:Xgetlist({'nr':'$'}).nr)
1994    call assert_equal(10, g:Xgetlist({'nr':1, 'items':1}).items[0].lnum)
1995    call assert_equal(20, g:Xgetlist({'nr':2, 'items':1}).items[0].lnum)
1996    call assert_equal(30, g:Xgetlist({'nr':3, 'items':1}).items[0].lnum)
1997    call g:Xsetlist([], 'f')
1998
1999    " Swap two quickfix lists
2000    Xexpr "File1:10:Line10"
2001    Xexpr "File2:20:Line20"
2002    Xexpr "File3:30:Line30"
2003    call g:Xsetlist([], 'r', {'nr':1,'title':'Colors','context':['Colors']})
2004    call g:Xsetlist([], 'r', {'nr':2,'title':'Fruits','context':['Fruits']})
2005    let l1=g:Xgetlist({'nr':1,'all':1})
2006    let l2=g:Xgetlist({'nr':2,'all':1})
2007    let save_id = l1.id
2008    let l1.id=l2.id
2009    let l2.id=save_id
2010    call g:Xsetlist([], 'r', l1)
2011    call g:Xsetlist([], 'r', l2)
2012    let newl1=g:Xgetlist({'nr':1,'all':1})
2013    let newl2=g:Xgetlist({'nr':2,'all':1})
2014    call assert_equal('Fruits', newl1.title)
2015    call assert_equal(['Fruits'], newl1.context)
2016    call assert_equal('Line20', newl1.items[0].text)
2017    call assert_equal('Colors', newl2.title)
2018    call assert_equal(['Colors'], newl2.context)
2019    call assert_equal('Line10', newl2.items[0].text)
2020    call g:Xsetlist([], 'f')
2021endfunc
2022
2023func Test_qf_property()
2024    call Xproperty_tests('c')
2025    call Xproperty_tests('l')
2026endfunc
2027
2028" Tests for the QuickFixCmdPre/QuickFixCmdPost autocommands
2029func QfAutoCmdHandler(loc, cmd)
2030  call add(g:acmds, a:loc . a:cmd)
2031endfunc
2032
2033func Test_Autocmd()
2034  autocmd QuickFixCmdPre * call QfAutoCmdHandler('pre', expand('<amatch>'))
2035  autocmd QuickFixCmdPost * call QfAutoCmdHandler('post', expand('<amatch>'))
2036
2037  let g:acmds = []
2038  cexpr "F1:10:Line 10"
2039  caddexpr "F1:20:Line 20"
2040  cgetexpr "F1:30:Line 30"
2041  cexpr ""
2042  caddexpr ""
2043  cgetexpr ""
2044  silent! cexpr non_existing_func()
2045  silent! caddexpr non_existing_func()
2046  silent! cgetexpr non_existing_func()
2047  let l = ['precexpr',
2048	      \ 'postcexpr',
2049	      \ 'precaddexpr',
2050	      \ 'postcaddexpr',
2051	      \ 'precgetexpr',
2052	      \ 'postcgetexpr',
2053	      \ 'precexpr',
2054	      \ 'postcexpr',
2055	      \ 'precaddexpr',
2056	      \ 'postcaddexpr',
2057	      \ 'precgetexpr',
2058	      \ 'postcgetexpr',
2059	      \ 'precexpr',
2060	      \ 'precaddexpr',
2061	      \ 'precgetexpr']
2062  call assert_equal(l, g:acmds)
2063
2064  let g:acmds = []
2065  enew! | call append(0, "F2:10:Line 10")
2066  cbuffer!
2067  enew! | call append(0, "F2:20:Line 20")
2068  cgetbuffer
2069  enew! | call append(0, "F2:30:Line 30")
2070  caddbuffer
2071  new
2072  let bnum = bufnr('%')
2073  bunload
2074  exe 'silent! cbuffer! ' . bnum
2075  exe 'silent! cgetbuffer ' . bnum
2076  exe 'silent! caddbuffer ' . bnum
2077  enew!
2078  let l = ['precbuffer',
2079	      \ 'postcbuffer',
2080	      \ 'precgetbuffer',
2081	      \ 'postcgetbuffer',
2082	      \ 'precaddbuffer',
2083	      \ 'postcaddbuffer',
2084	      \ 'precbuffer',
2085	      \ 'precgetbuffer',
2086	      \ 'precaddbuffer']
2087  call assert_equal(l, g:acmds)
2088
2089  call writefile(['Xtest:1:Line1'], 'Xtest')
2090  call writefile([], 'Xempty')
2091  let g:acmds = []
2092  cfile Xtest
2093  caddfile Xtest
2094  cgetfile Xtest
2095  cfile Xempty
2096  caddfile Xempty
2097  cgetfile Xempty
2098  silent! cfile do_not_exist
2099  silent! caddfile do_not_exist
2100  silent! cgetfile do_not_exist
2101  let l = ['precfile',
2102	      \ 'postcfile',
2103	      \ 'precaddfile',
2104	      \ 'postcaddfile',
2105	      \ 'precgetfile',
2106	      \ 'postcgetfile',
2107	      \ 'precfile',
2108	      \ 'postcfile',
2109	      \ 'precaddfile',
2110	      \ 'postcaddfile',
2111	      \ 'precgetfile',
2112	      \ 'postcgetfile',
2113	      \ 'precfile',
2114	      \ 'postcfile',
2115	      \ 'precaddfile',
2116	      \ 'postcaddfile',
2117	      \ 'precgetfile',
2118	      \ 'postcgetfile']
2119  call assert_equal(l, g:acmds)
2120
2121  let g:acmds = []
2122  helpgrep quickfix
2123  silent! helpgrep non_existing_help_topic
2124  vimgrep test Xtest
2125  vimgrepadd test Xtest
2126  silent! vimgrep non_existing_test Xtest
2127  silent! vimgrepadd non_existing_test Xtest
2128  set makeprg=
2129  silent! make
2130  set makeprg&
2131  let l = ['prehelpgrep',
2132	      \ 'posthelpgrep',
2133	      \ 'prehelpgrep',
2134	      \ 'posthelpgrep',
2135	      \ 'previmgrep',
2136	      \ 'postvimgrep',
2137	      \ 'previmgrepadd',
2138	      \ 'postvimgrepadd',
2139	      \ 'previmgrep',
2140	      \ 'postvimgrep',
2141	      \ 'previmgrepadd',
2142	      \ 'postvimgrepadd',
2143	      \ 'premake',
2144	      \ 'postmake']
2145  call assert_equal(l, g:acmds)
2146
2147  if has('unix')
2148    " Run this test only on Unix-like systems. The grepprg may not be set on
2149    " non-Unix systems.
2150    " The following lines are used for the grep test. Don't remove.
2151    " Grep_Autocmd_Text: Match 1
2152    " GrepAdd_Autocmd_Text: Match 2
2153    let g:acmds = []
2154    silent grep Grep_Autocmd_Text test_quickfix.vim
2155    silent grepadd GrepAdd_Autocmd_Text test_quickfix.vim
2156    silent grep abc123def Xtest
2157    silent grepadd abc123def Xtest
2158    let l = ['pregrep',
2159		\ 'postgrep',
2160		\ 'pregrepadd',
2161		\ 'postgrepadd',
2162		\ 'pregrep',
2163		\ 'postgrep',
2164		\ 'pregrepadd',
2165		\ 'postgrepadd']
2166    call assert_equal(l, g:acmds)
2167  endif
2168
2169  call delete('Xtest')
2170  call delete('Xempty')
2171  au! QuickFixCmdPre
2172  au! QuickFixCmdPost
2173endfunc
2174
2175func Test_Autocmd_Exception()
2176  set efm=%m
2177  lgetexpr '?'
2178
2179  try
2180    call DoesNotExit()
2181  catch
2182    lgetexpr '1'
2183  finally
2184    lgetexpr '1'
2185  endtry
2186
2187  call assert_equal('1', getloclist(0)[0].text)
2188
2189  set efm&vim
2190endfunc
2191
2192func Test_caddbuffer_wrong()
2193  " This used to cause a memory access in freed memory.
2194  let save_efm = &efm
2195  set efm=%EEEE%m,%WWWW,%+CCCC%>%#,%GGGG%.#
2196  cgetexpr ['WWWW', 'EEEE', 'CCCC']
2197  let &efm = save_efm
2198  caddbuffer
2199  bwipe!
2200endfunc
2201
2202func Test_caddexpr_wrong()
2203  " This used to cause a memory access in freed memory.
2204  cbuffer
2205  cbuffer
2206  copen
2207  let save_efm = &efm
2208  set efm=%
2209  call assert_fails('caddexpr ""', 'E376:')
2210  let &efm = save_efm
2211endfunc
2212
2213func Test_dirstack_cleanup()
2214  " This used to cause a memory access in freed memory.
2215  let save_efm = &efm
2216  lexpr '0'
2217  lopen
2218  fun X(c)
2219    let save_efm=&efm
2220    set efm=%D%f
2221    if a:c == 'c'
2222      caddexpr '::'
2223    else
2224      laddexpr ':0:0'
2225    endif
2226    let &efm=save_efm
2227  endfun
2228  call X('c')
2229  call X('l')
2230  call setqflist([], 'r')
2231  caddbuffer
2232  let &efm = save_efm
2233endfunc
2234
2235" Tests for jumping to entries from the location list window and quickfix
2236" window
2237func Test_cwindow_jump()
2238  set efm=%f%%%l%%%m
2239  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2240  lopen | only
2241  lfirst
2242  call assert_true(winnr('$') == 2)
2243  call assert_true(winnr() == 1)
2244  " Location list for the new window should be set
2245  call assert_true(getloclist(0)[2].text == 'Line 30')
2246
2247  " Open a scratch buffer
2248  " Open a new window and create a location list
2249  " Open the location list window and close the other window
2250  " Jump to an entry.
2251  " Should create a new window and jump to the entry. The scrtach buffer
2252  " should not be used.
2253  enew | only
2254  set buftype=nofile
2255  below new
2256  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2257  lopen
2258  2wincmd c
2259  lnext
2260  call assert_true(winnr('$') == 3)
2261  call assert_true(winnr() == 2)
2262
2263  " Open two windows with two different location lists
2264  " Open the location list window and close the previous window
2265  " Jump to an entry in the location list window
2266  " Should open the file in the first window and not set the location list.
2267  enew | only
2268  lgetexpr ["F1%5%Line 5"]
2269  below new
2270  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2271  lopen
2272  2wincmd c
2273  lnext
2274  call assert_true(winnr() == 1)
2275  call assert_true(getloclist(0)[0].text == 'Line 5')
2276
2277  enew | only
2278  cgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2279  copen
2280  cnext
2281  call assert_true(winnr('$') == 2)
2282  call assert_true(winnr() == 1)
2283
2284  enew | only
2285  set efm&vim
2286endfunc
2287
2288func XvimgrepTests(cchar)
2289  call s:setup_commands(a:cchar)
2290
2291  call writefile(['Editor:VIM vim',
2292	      \ 'Editor:Emacs EmAcS',
2293	      \ 'Editor:Notepad NOTEPAD'], 'Xtestfile1')
2294  call writefile(['Linux', 'MacOS', 'MS-Windows'], 'Xtestfile2')
2295
2296  " Error cases
2297  call assert_fails('Xvimgrep /abc *', 'E682:')
2298
2299  let @/=''
2300  call assert_fails('Xvimgrep // *', 'E35:')
2301
2302  call assert_fails('Xvimgrep abc', 'E683:')
2303  call assert_fails('Xvimgrep a1b2c3 Xtestfile1', 'E480:')
2304  call assert_fails('Xvimgrep pat Xa1b2c3', 'E480:')
2305
2306  Xexpr ""
2307  Xvimgrepadd Notepad Xtestfile1
2308  Xvimgrepadd MacOS Xtestfile2
2309  let l = g:Xgetlist()
2310  call assert_equal(2, len(l))
2311  call assert_equal('Editor:Notepad NOTEPAD', l[0].text)
2312
2313  Xvimgrep #\cvim#g Xtestfile?
2314  let l = g:Xgetlist()
2315  call assert_equal(2, len(l))
2316  call assert_equal(8, l[0].col)
2317  call assert_equal(12, l[1].col)
2318
2319  1Xvimgrep ?Editor? Xtestfile*
2320  let l = g:Xgetlist()
2321  call assert_equal(1, len(l))
2322  call assert_equal('Editor:VIM vim', l[0].text)
2323
2324  edit +3 Xtestfile2
2325  Xvimgrep +\cemacs+j Xtestfile1
2326  let l = g:Xgetlist()
2327  call assert_equal('Xtestfile2', bufname(''))
2328  call assert_equal('Editor:Emacs EmAcS', l[0].text)
2329
2330  " Test for unloading a buffer after vimgrep searched the buffer
2331  %bwipe
2332  Xvimgrep /Editor/j Xtestfile*
2333  call assert_equal(0, getbufinfo('Xtestfile1')[0].loaded)
2334  call assert_equal([], getbufinfo('Xtestfile2'))
2335
2336  call delete('Xtestfile1')
2337  call delete('Xtestfile2')
2338endfunc
2339
2340" Tests for the :vimgrep command
2341func Test_vimgrep()
2342  call XvimgrepTests('c')
2343  call XvimgrepTests('l')
2344endfunc
2345
2346func XfreeTests(cchar)
2347  call s:setup_commands(a:cchar)
2348
2349  enew | only
2350
2351  " Deleting the quickfix stack should work even When the current list is
2352  " somewhere in the middle of the stack
2353  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2354  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2355  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2356  Xolder
2357  call g:Xsetlist([], 'f')
2358  call assert_equal(0, len(g:Xgetlist()))
2359
2360  " After deleting the stack, adding a new list should create a stack with a
2361  " single list.
2362  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2363  call assert_equal(1, g:Xgetlist({'all':1}).nr)
2364
2365  " Deleting the stack from a quickfix window should update/clear the
2366  " quickfix/location list window.
2367  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2368  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2369  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2370  Xolder
2371  Xwindow
2372  call g:Xsetlist([], 'f')
2373  call assert_equal(2, winnr('$'))
2374  call assert_equal(1, line('$'))
2375  Xclose
2376
2377  " Deleting the stack from a non-quickfix window should update/clear the
2378  " quickfix/location list window.
2379  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2380  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2381  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2382  Xolder
2383  Xwindow
2384  wincmd p
2385  call g:Xsetlist([], 'f')
2386  call assert_equal(0, len(g:Xgetlist()))
2387  wincmd p
2388  call assert_equal(2, winnr('$'))
2389  call assert_equal(1, line('$'))
2390
2391  " After deleting the location list stack, if the location list window is
2392  " opened, then a new location list should be created. So opening the
2393  " location list window again should not create a new window.
2394  if a:cchar == 'l'
2395      lexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2396      wincmd p
2397      lopen
2398      call assert_equal(2, winnr('$'))
2399  endif
2400  Xclose
2401endfunc
2402
2403" Tests for the quickfix free functionality
2404func Test_qf_free()
2405  call XfreeTests('c')
2406  call XfreeTests('l')
2407endfunc
2408
2409" Test for buffer overflow when parsing lines and adding new entries to
2410" the quickfix list.
2411func Test_bufoverflow()
2412  set efm=%f:%l:%m
2413  cgetexpr ['File1:100:' . repeat('x', 1025)]
2414
2415  set efm=%+GCompiler:\ %.%#,%f:%l:%m
2416  cgetexpr ['Compiler: ' . repeat('a', 1015), 'File1:10:Hello World']
2417
2418  set efm=%DEntering\ directory\ %f,%f:%l:%m
2419  cgetexpr ['Entering directory ' . repeat('a', 1006),
2420	      \ 'File1:10:Hello World']
2421  set efm&vim
2422endfunc
2423
2424" Tests for getting the quickfix stack size
2425func XsizeTests(cchar)
2426  call s:setup_commands(a:cchar)
2427
2428  call g:Xsetlist([], 'f')
2429  call assert_equal(0, g:Xgetlist({'nr':'$'}).nr)
2430  call assert_equal('', g:Xgetlist({'nr':'$', 'all':1}).title)
2431  call assert_equal(0, g:Xgetlist({'nr':0}).nr)
2432
2433  Xexpr "File1:10:Line1"
2434  Xexpr "File2:20:Line2"
2435  Xexpr "File3:30:Line3"
2436  Xolder | Xolder
2437  call assert_equal(3, g:Xgetlist({'nr':'$'}).nr)
2438  call g:Xsetlist([], 'f')
2439
2440  Xexpr "File1:10:Line1"
2441  Xexpr "File2:20:Line2"
2442  Xexpr "File3:30:Line3"
2443  Xolder | Xolder
2444  call g:Xsetlist([], 'a', {'nr':'$', 'title':'Compiler'})
2445  call assert_equal('Compiler', g:Xgetlist({'nr':3, 'all':1}).title)
2446endfunc
2447
2448func Test_Qf_Size()
2449  call XsizeTests('c')
2450  call XsizeTests('l')
2451endfunc
2452
2453func Test_cclose_from_copen()
2454    augroup QF_Test
2455	au!
2456        au FileType qf :call assert_fails(':cclose', 'E788')
2457    augroup END
2458    copen
2459    augroup QF_Test
2460	au!
2461    augroup END
2462    augroup! QF_Test
2463endfunc
2464
2465func Test_cclose_in_autocmd()
2466  " Problem is only triggered if "starting" is zero, so that the OptionsSet
2467  " event will be triggered.
2468  call test_override('starting', 1)
2469  augroup QF_Test
2470    au!
2471    au FileType qf :call assert_fails(':cclose', 'E788')
2472  augroup END
2473  copen
2474  augroup QF_Test
2475    au!
2476  augroup END
2477  augroup! QF_Test
2478  call test_override('starting', 0)
2479endfunc
2480
2481func Test_resize_from_copen()
2482    augroup QF_Test
2483	au!
2484        au FileType qf resize 5
2485    augroup END
2486    try
2487	" This should succeed without any exception.  No other buffers are
2488	" involved in the autocmd.
2489	copen
2490    finally
2491	augroup QF_Test
2492	    au!
2493	augroup END
2494	augroup! QF_Test
2495    endtry
2496endfunc
2497
2498" Tests for the quickfix buffer b:changedtick variable
2499func Xchangedtick_tests(cchar)
2500  call s:setup_commands(a:cchar)
2501
2502  new | only
2503
2504  Xexpr "" | Xexpr "" | Xexpr ""
2505
2506  Xopen
2507  Xolder
2508  Xolder
2509  Xaddexpr "F1:10:Line10"
2510  Xaddexpr "F2:20:Line20"
2511  call g:Xsetlist([{"filename":"F3", "lnum":30, "text":"Line30"}], 'a')
2512  call g:Xsetlist([], 'f')
2513  call assert_equal(8, getbufvar('%', 'changedtick'))
2514  Xclose
2515endfunc
2516
2517func Test_changedtick()
2518  call Xchangedtick_tests('c')
2519  call Xchangedtick_tests('l')
2520endfunc
2521
2522" Tests for parsing an expression using setqflist()
2523func Xsetexpr_tests(cchar)
2524  call s:setup_commands(a:cchar)
2525
2526  let t = ["File1:10:Line10", "File1:20:Line20"]
2527  call g:Xsetlist([], ' ', {'lines' : t})
2528  call g:Xsetlist([], 'a', {'lines' : ["File1:30:Line30"]})
2529
2530  let l = g:Xgetlist()
2531  call assert_equal(3, len(l))
2532  call assert_equal(20, l[1].lnum)
2533  call assert_equal('Line30', l[2].text)
2534  call g:Xsetlist([], 'r', {'lines' : ["File2:5:Line5"]})
2535  let l = g:Xgetlist()
2536  call assert_equal(1, len(l))
2537  call assert_equal('Line5', l[0].text)
2538  call assert_equal(-1, g:Xsetlist([], 'a', {'lines' : 10}))
2539  call assert_equal(-1, g:Xsetlist([], 'a', {'lines' : "F1:10:L10"}))
2540
2541  call g:Xsetlist([], 'f')
2542  " Add entries to multiple lists
2543  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["File1:10:Line10"]})
2544  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["File2:20:Line20"]})
2545  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["File1:15:Line15"]})
2546  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["File2:25:Line25"]})
2547  call assert_equal('Line15', g:Xgetlist({'nr':1, 'items':1}).items[1].text)
2548  call assert_equal('Line25', g:Xgetlist({'nr':2, 'items':1}).items[1].text)
2549
2550  " Adding entries using a custom efm
2551  set efm&
2552  call g:Xsetlist([], ' ', {'efm' : '%f#%l#%m',
2553				\ 'lines' : ["F1#10#L10", "F2#20#L20"]})
2554  call assert_equal(20, g:Xgetlist({'items':1}).items[1].lnum)
2555  call g:Xsetlist([], 'a', {'efm' : '%f#%l#%m', 'lines' : ["F3:30:L30"]})
2556  call assert_equal('F3:30:L30', g:Xgetlist({'items':1}).items[2].text)
2557  call assert_equal(20, g:Xgetlist({'items':1}).items[1].lnum)
2558  call assert_equal(-1, g:Xsetlist([], 'a', {'efm' : [],
2559				\ 'lines' : ['F1:10:L10']}))
2560endfunc
2561
2562func Test_setexpr()
2563  call Xsetexpr_tests('c')
2564  call Xsetexpr_tests('l')
2565endfunc
2566
2567" Tests for per quickfix/location list directory stack
2568func Xmultidirstack_tests(cchar)
2569  call s:setup_commands(a:cchar)
2570
2571  call g:Xsetlist([], 'f')
2572  Xexpr "" | Xexpr ""
2573
2574  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["Entering dir 'Xone/a'"]})
2575  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["Entering dir 'Xtwo/a'"]})
2576  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["one.txt:3:one one one"]})
2577  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["two.txt:5:two two two"]})
2578
2579  let l1 = g:Xgetlist({'nr':1, 'items':1})
2580  let l2 = g:Xgetlist({'nr':2, 'items':1})
2581  call assert_equal('Xone/a/one.txt', bufname(l1.items[1].bufnr))
2582  call assert_equal(3, l1.items[1].lnum)
2583  call assert_equal('Xtwo/a/two.txt', bufname(l2.items[1].bufnr))
2584  call assert_equal(5, l2.items[1].lnum)
2585endfunc
2586
2587func Test_multidirstack()
2588  call mkdir('Xone/a', 'p')
2589  call mkdir('Xtwo/a', 'p')
2590  let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7']
2591  call writefile(lines, 'Xone/a/one.txt')
2592  call writefile(lines, 'Xtwo/a/two.txt')
2593  let save_efm = &efm
2594  set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f'
2595
2596  call Xmultidirstack_tests('c')
2597  call Xmultidirstack_tests('l')
2598
2599  let &efm = save_efm
2600  call delete('Xone', 'rf')
2601  call delete('Xtwo', 'rf')
2602endfunc
2603
2604" Tests for per quickfix/location list file stack
2605func Xmultifilestack_tests(cchar)
2606  call s:setup_commands(a:cchar)
2607
2608  call g:Xsetlist([], 'f')
2609  Xexpr "" | Xexpr ""
2610
2611  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["[one.txt]"]})
2612  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["[two.txt]"]})
2613  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["(3,5) one one one"]})
2614  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["(5,9) two two two"]})
2615
2616  let l1 = g:Xgetlist({'nr':1, 'items':1})
2617  let l2 = g:Xgetlist({'nr':2, 'items':1})
2618  call assert_equal('one.txt', bufname(l1.items[1].bufnr))
2619  call assert_equal(3, l1.items[1].lnum)
2620  call assert_equal('two.txt', bufname(l2.items[1].bufnr))
2621  call assert_equal(5, l2.items[1].lnum)
2622
2623  " Test for start of a new error line in the same line where a previous
2624  " error line ends with a file stack.
2625  let efm_val = 'Error\ l%l\ in\ %f,'
2626  let efm_val .= '%-P%>(%f%r,Error\ l%l\ in\ %m,%-Q)%r'
2627  let l = g:Xgetlist({'lines' : [
2628	      \ '(one.txt',
2629	      \ 'Error l4 in one.txt',
2630	      \ ') (two.txt',
2631	      \ 'Error l6 in two.txt',
2632	      \ ')',
2633	      \ 'Error l8 in one.txt'
2634	      \ ], 'efm' : efm_val})
2635  call assert_equal(3, len(l.items))
2636  call assert_equal('one.txt', bufname(l.items[0].bufnr))
2637  call assert_equal(4, l.items[0].lnum)
2638  call assert_equal('one.txt', l.items[0].text)
2639  call assert_equal('two.txt', bufname(l.items[1].bufnr))
2640  call assert_equal(6, l.items[1].lnum)
2641  call assert_equal('two.txt', l.items[1].text)
2642  call assert_equal('one.txt', bufname(l.items[2].bufnr))
2643  call assert_equal(8, l.items[2].lnum)
2644  call assert_equal('', l.items[2].text)
2645endfunc
2646
2647func Test_multifilestack()
2648  let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7']
2649  call writefile(lines, 'one.txt')
2650  call writefile(lines, 'two.txt')
2651  let save_efm = &efm
2652  set efm=%+P[%f],(%l\\,%c)\ %m,%-Q
2653
2654  call Xmultifilestack_tests('c')
2655  call Xmultifilestack_tests('l')
2656
2657  let &efm = save_efm
2658  call delete('one.txt')
2659  call delete('two.txt')
2660endfunc
2661
2662" Tests for per buffer 'efm' setting
2663func Test_perbuf_efm()
2664  call writefile(["File1-10-Line10"], 'one.txt')
2665  call writefile(["File2#20#Line20"], 'two.txt')
2666  set efm=%f#%l#%m
2667  new | only
2668  new
2669  setlocal efm=%f-%l-%m
2670  cfile one.txt
2671  wincmd w
2672  caddfile two.txt
2673
2674  let l = getqflist()
2675  call assert_equal(10, l[0].lnum)
2676  call assert_equal('Line20', l[1].text)
2677
2678  set efm&
2679  new | only
2680  call delete('one.txt')
2681  call delete('two.txt')
2682endfunc
2683
2684" Open multiple help windows using ":lhelpgrep
2685" This test used to crash Vim
2686func Test_Multi_LL_Help()
2687    new | only
2688    lhelpgrep window
2689    lopen
2690    e#
2691    lhelpgrep buffer
2692    call assert_equal(3, winnr('$'))
2693    call assert_true(len(getloclist(1)) != 0)
2694    call assert_true(len(getloclist(2)) != 0)
2695    new | only
2696endfunc
2697
2698" Tests for adding new quickfix lists using setqflist()
2699func XaddQf_tests(cchar)
2700  call s:setup_commands(a:cchar)
2701
2702  " Create a new list using ' ' for action
2703  call g:Xsetlist([], 'f')
2704  call g:Xsetlist([], ' ', {'title' : 'Test1'})
2705  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2706  call assert_equal(1, l.nr)
2707  call assert_equal('Test1', l.title)
2708
2709  " Create a new list using ' ' for action and '$' for 'nr'
2710  call g:Xsetlist([], 'f')
2711  call g:Xsetlist([], ' ', {'title' : 'Test2', 'nr' : '$'})
2712  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2713  call assert_equal(1, l.nr)
2714  call assert_equal('Test2', l.title)
2715
2716  " Create a new list using 'a' for action
2717  call g:Xsetlist([], 'f')
2718  call g:Xsetlist([], 'a', {'title' : 'Test3'})
2719  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2720  call assert_equal(1, l.nr)
2721  call assert_equal('Test3', l.title)
2722
2723  " Create a new list using 'a' for action and '$' for 'nr'
2724  call g:Xsetlist([], 'f')
2725  call g:Xsetlist([], 'a', {'title' : 'Test3', 'nr' : '$'})
2726  call g:Xsetlist([], 'a', {'title' : 'Test4'})
2727  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2728  call assert_equal(1, l.nr)
2729  call assert_equal('Test4', l.title)
2730
2731  " Adding a quickfix list should remove all the lists following the current
2732  " list.
2733  Xexpr "" | Xexpr "" | Xexpr ""
2734  silent! 10Xolder
2735  call g:Xsetlist([], ' ', {'title' : 'Test5'})
2736  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2737  call assert_equal(2, l.nr)
2738  call assert_equal('Test5', l.title)
2739
2740  " Add a quickfix list using '$' as the list number.
2741  let lastqf = g:Xgetlist({'nr':'$'}).nr
2742  silent! 99Xolder
2743  call g:Xsetlist([], ' ', {'nr' : '$', 'title' : 'Test6'})
2744  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2745  call assert_equal(lastqf + 1, l.nr)
2746  call assert_equal('Test6', l.title)
2747
2748  " Add a quickfix list using 'nr' set to one more than the quickfix
2749  " list size.
2750  let lastqf = g:Xgetlist({'nr':'$'}).nr
2751  silent! 99Xolder
2752  call g:Xsetlist([], ' ', {'nr' : lastqf + 1, 'title' : 'Test7'})
2753  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2754  call assert_equal(lastqf + 1, l.nr)
2755  call assert_equal('Test7', l.title)
2756
2757  " Add a quickfix list to a stack with 10 lists using 'nr' set to '$'
2758  exe repeat('Xexpr "" |', 9) . 'Xexpr ""'
2759  silent! 99Xolder
2760  call g:Xsetlist([], ' ', {'nr' : '$', 'title' : 'Test8'})
2761  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2762  call assert_equal(10, l.nr)
2763  call assert_equal('Test8', l.title)
2764
2765  " Add a quickfix list using 'nr' set to a value greater than 10
2766  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : 12, 'title' : 'Test9'}))
2767
2768  " Try adding a quickfix list with 'nr' set to a value greater than the
2769  " quickfix list size but less than 10.
2770  call g:Xsetlist([], 'f')
2771  Xexpr "" | Xexpr "" | Xexpr ""
2772  silent! 99Xolder
2773  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : 8, 'title' : 'Test10'}))
2774
2775  " Add a quickfix list using 'nr' set to a some string or list
2776  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : [1,2], 'title' : 'Test11'}))
2777endfunc
2778
2779func Test_add_qf()
2780  call XaddQf_tests('c')
2781  call XaddQf_tests('l')
2782endfunc
2783
2784" Test for getting the quickfix list items from some text without modifying
2785" the quickfix stack
2786func XgetListFromLines(cchar)
2787  call s:setup_commands(a:cchar)
2788  call g:Xsetlist([], 'f')
2789
2790  let l = g:Xgetlist({'lines' : ["File2:20:Line20", "File2:30:Line30"]}).items
2791  call assert_equal(2, len(l))
2792  call assert_equal(30, l[1].lnum)
2793
2794  call assert_equal({}, g:Xgetlist({'lines' : 10}))
2795  call assert_equal({}, g:Xgetlist({'lines' : 'File1:10:Line10'}))
2796  call assert_equal([], g:Xgetlist({'lines' : []}).items)
2797  call assert_equal([], g:Xgetlist({'lines' : [10, 20]}).items)
2798
2799  " Parse text using a custom efm
2800  set efm&
2801  let l = g:Xgetlist({'lines':['File3#30#Line30'], 'efm' : '%f#%l#%m'}).items
2802  call assert_equal('Line30', l[0].text)
2803  let l = g:Xgetlist({'lines':['File3:30:Line30'], 'efm' : '%f-%l-%m'}).items
2804  call assert_equal('File3:30:Line30', l[0].text)
2805  let l = g:Xgetlist({'lines':['File3:30:Line30'], 'efm' : [1,2]})
2806  call assert_equal({}, l)
2807  call assert_fails("call g:Xgetlist({'lines':['abc'], 'efm':'%2'})", 'E376:')
2808  call assert_fails("call g:Xgetlist({'lines':['abc'], 'efm':''})", 'E378:')
2809
2810  " Make sure that the quickfix stack is not modified
2811  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
2812endfunc
2813
2814func Test_get_list_from_lines()
2815  call XgetListFromLines('c')
2816  call XgetListFromLines('l')
2817endfunc
2818
2819" Tests for the quickfix list id
2820func Xqfid_tests(cchar)
2821  call s:setup_commands(a:cchar)
2822
2823  call g:Xsetlist([], 'f')
2824  call assert_equal(0, g:Xgetlist({'id':0}).id)
2825  Xexpr ''
2826  let start_id = g:Xgetlist({'id' : 0}).id
2827  Xexpr '' | Xexpr ''
2828  Xolder
2829  call assert_equal(start_id, g:Xgetlist({'id':0, 'nr':1}).id)
2830  call assert_equal(start_id + 1, g:Xgetlist({'id':0, 'nr':0}).id)
2831  call assert_equal(start_id + 2, g:Xgetlist({'id':0, 'nr':'$'}).id)
2832  call assert_equal(0, g:Xgetlist({'id':0, 'nr':99}).id)
2833  call assert_equal(2, g:Xgetlist({'id':start_id + 1, 'nr':0}).nr)
2834  call assert_equal(0, g:Xgetlist({'id':99, 'nr':0}).id)
2835  call assert_equal(0, g:Xgetlist({'id':"abc", 'nr':0}).id)
2836
2837  call g:Xsetlist([], 'a', {'id':start_id, 'context':[1,2]})
2838  call assert_equal([1,2], g:Xgetlist({'nr':1, 'context':1}).context)
2839  call g:Xsetlist([], 'a', {'id':start_id+1, 'lines':['F1:10:L10']})
2840  call assert_equal('L10', g:Xgetlist({'nr':2, 'items':1}).items[0].text)
2841  call assert_equal(-1, g:Xsetlist([], 'a', {'id':999, 'title':'Vim'}))
2842  call assert_equal(-1, g:Xsetlist([], 'a', {'id':'abc', 'title':'Vim'}))
2843
2844  let qfid = g:Xgetlist({'id':0, 'nr':0})
2845  call g:Xsetlist([], 'f')
2846  call assert_equal(0, g:Xgetlist({'id':qfid, 'nr':0}).id)
2847endfunc
2848
2849func Test_qf_id()
2850  call Xqfid_tests('c')
2851  call Xqfid_tests('l')
2852endfunc
2853
2854func Xqfjump_tests(cchar)
2855  call s:setup_commands(a:cchar)
2856
2857  call writefile(["Line1\tFoo", "Line2"], 'F1')
2858  call writefile(["Line1\tBar", "Line2"], 'F2')
2859  call writefile(["Line1\tBaz", "Line2"], 'F3')
2860
2861  call g:Xsetlist([], 'f')
2862
2863  " Tests for
2864  "   Jumping to a line using a pattern
2865  "   Jumping to a column greater than the last column in a line
2866  "   Jumping to a line greater than the last line in the file
2867  let l = []
2868  for i in range(1, 7)
2869    call add(l, {})
2870  endfor
2871  let l[0].filename='F1'
2872  let l[0].pattern='Line1'
2873  let l[1].filename='F2'
2874  let l[1].pattern='Line1'
2875  let l[2].filename='F3'
2876  let l[2].pattern='Line1'
2877  let l[3].filename='F3'
2878  let l[3].lnum=1
2879  let l[3].col=9
2880  let l[3].vcol=1
2881  let l[4].filename='F3'
2882  let l[4].lnum=99
2883  let l[5].filename='F3'
2884  let l[5].lnum=1
2885  let l[5].col=99
2886  let l[5].vcol=1
2887  let l[6].filename='F3'
2888  let l[6].pattern='abcxyz'
2889
2890  call g:Xsetlist([], ' ', {'items' : l})
2891  Xopen | only
2892  2Xnext
2893  call assert_equal(3, g:Xgetlist({'idx' : 0}).idx)
2894  call assert_equal('F3', bufname('%'))
2895  Xnext
2896  call assert_equal(7, col('.'))
2897  Xnext
2898  call assert_equal(2, line('.'))
2899  Xnext
2900  call assert_equal(9, col('.'))
2901  2
2902  Xnext
2903  call assert_equal(2, line('.'))
2904
2905  if a:cchar == 'l'
2906    " When jumping to a location list entry in the location list window and
2907    " no usable windows are available, then a new window should be opened.
2908    enew! | new | only
2909    call g:Xsetlist([], 'f')
2910    setlocal buftype=nofile
2911    new
2912    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']})
2913    Xopen
2914    let winid = win_getid()
2915    wincmd p
2916    close
2917    call win_gotoid(winid)
2918    Xnext
2919    call assert_equal(3, winnr('$'))
2920    call assert_equal(1, winnr())
2921    call assert_equal(2, line('.'))
2922
2923    " When jumping to an entry in the location list window and the window
2924    " associated with the location list is not present and a window containing
2925    " the file is already present, then that window should be used.
2926    close
2927    belowright new
2928    call g:Xsetlist([], 'f')
2929    edit F3
2930    call win_gotoid(winid)
2931    Xlast
2932    call assert_equal(3, winnr())
2933    call assert_equal(6, g:Xgetlist({'size' : 1}).size)
2934    call assert_equal(winid, g:Xgetlist({'winid' : 1}).winid)
2935  endif
2936
2937  " Cleanup
2938  enew!
2939  new | only
2940
2941  call delete('F1')
2942  call delete('F2')
2943  call delete('F3')
2944endfunc
2945
2946func Test_qfjump()
2947  call Xqfjump_tests('c')
2948  call Xqfjump_tests('l')
2949endfunc
2950
2951" Tests for the getqflist() and getloclist() functions when the list is not
2952" present or is empty
2953func Xgetlist_empty_tests(cchar)
2954  call s:setup_commands(a:cchar)
2955
2956  " Empty quickfix stack
2957  call g:Xsetlist([], 'f')
2958  call assert_equal('', g:Xgetlist({'context' : 0}).context)
2959  call assert_equal(0, g:Xgetlist({'id' : 0}).id)
2960  call assert_equal(0, g:Xgetlist({'idx' : 0}).idx)
2961  call assert_equal([], g:Xgetlist({'items' : 0}).items)
2962  call assert_equal(0, g:Xgetlist({'nr' : 0}).nr)
2963  call assert_equal(0, g:Xgetlist({'size' : 0}).size)
2964  call assert_equal('', g:Xgetlist({'title' : 0}).title)
2965  call assert_equal(0, g:Xgetlist({'winid' : 0}).winid)
2966  call assert_equal(0, g:Xgetlist({'changedtick' : 0}).changedtick)
2967  call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [], 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0, 'changedtick': 0}, g:Xgetlist({'all' : 0}))
2968
2969  " Quickfix window with empty stack
2970  silent! Xopen
2971  let qfwinid = (a:cchar == 'c') ? win_getid() : 0
2972  call assert_equal(qfwinid, g:Xgetlist({'winid' : 0}).winid)
2973  Xclose
2974
2975  " Empty quickfix list
2976  Xexpr ""
2977  call assert_equal('', g:Xgetlist({'context' : 0}).context)
2978  call assert_notequal(0, g:Xgetlist({'id' : 0}).id)
2979  call assert_equal(0, g:Xgetlist({'idx' : 0}).idx)
2980  call assert_equal([], g:Xgetlist({'items' : 0}).items)
2981  call assert_notequal(0, g:Xgetlist({'nr' : 0}).nr)
2982  call assert_equal(0, g:Xgetlist({'size' : 0}).size)
2983  call assert_notequal('', g:Xgetlist({'title' : 0}).title)
2984  call assert_equal(0, g:Xgetlist({'winid' : 0}).winid)
2985  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
2986
2987  let qfid = g:Xgetlist({'id' : 0}).id
2988  call g:Xsetlist([], 'f')
2989
2990  " Non-existing quickfix identifier
2991  call assert_equal('', g:Xgetlist({'id' : qfid, 'context' : 0}).context)
2992  call assert_equal(0, g:Xgetlist({'id' : qfid}).id)
2993  call assert_equal(0, g:Xgetlist({'id' : qfid, 'idx' : 0}).idx)
2994  call assert_equal([], g:Xgetlist({'id' : qfid, 'items' : 0}).items)
2995  call assert_equal(0, g:Xgetlist({'id' : qfid, 'nr' : 0}).nr)
2996  call assert_equal(0, g:Xgetlist({'id' : qfid, 'size' : 0}).size)
2997  call assert_equal('', g:Xgetlist({'id' : qfid, 'title' : 0}).title)
2998  call assert_equal(0, g:Xgetlist({'id' : qfid, 'winid' : 0}).winid)
2999  call assert_equal(0, g:Xgetlist({'id' : qfid, 'changedtick' : 0}).changedtick)
3000  call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [], 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0, 'changedtick' : 0}, g:Xgetlist({'id' : qfid, 'all' : 0}))
3001
3002  " Non-existing quickfix list number
3003  call assert_equal('', g:Xgetlist({'nr' : 5, 'context' : 0}).context)
3004  call assert_equal(0, g:Xgetlist({'nr' : 5}).nr)
3005  call assert_equal(0, g:Xgetlist({'nr' : 5, 'idx' : 0}).idx)
3006  call assert_equal([], g:Xgetlist({'nr' : 5, 'items' : 0}).items)
3007  call assert_equal(0, g:Xgetlist({'nr' : 5, 'id' : 0}).id)
3008  call assert_equal(0, g:Xgetlist({'nr' : 5, 'size' : 0}).size)
3009  call assert_equal('', g:Xgetlist({'nr' : 5, 'title' : 0}).title)
3010  call assert_equal(0, g:Xgetlist({'nr' : 5, 'winid' : 0}).winid)
3011  call assert_equal(0, g:Xgetlist({'nr' : 5, 'changedtick' : 0}).changedtick)
3012  call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [], 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0, 'changedtick' : 0}, g:Xgetlist({'nr' : 5, 'all' : 0}))
3013endfunc
3014
3015func Test_getqflist()
3016  call Xgetlist_empty_tests('c')
3017  call Xgetlist_empty_tests('l')
3018endfunc
3019
3020func Test_getqflist_invalid_nr()
3021  " The following commands used to crash Vim
3022  cexpr ""
3023  call getqflist({'nr' : $XXX_DOES_NOT_EXIST_XXX})
3024
3025  " Cleanup
3026  call setqflist([], 'r')
3027endfunc
3028
3029" Tests for the quickfix/location list changedtick
3030func Xqftick_tests(cchar)
3031  call s:setup_commands(a:cchar)
3032
3033  call g:Xsetlist([], 'f')
3034
3035  Xexpr "F1:10:Line10"
3036  let qfid = g:Xgetlist({'id' : 0}).id
3037  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3038  Xaddexpr "F2:20:Line20\nF2:21:Line21"
3039  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
3040  call g:Xsetlist([], 'a', {'lines' : ["F3:30:Line30", "F3:31:Line31"]})
3041  call assert_equal(3, g:Xgetlist({'changedtick' : 0}).changedtick)
3042  call g:Xsetlist([], 'r', {'lines' : ["F4:40:Line40"]})
3043  call assert_equal(4, g:Xgetlist({'changedtick' : 0}).changedtick)
3044  call g:Xsetlist([], 'a', {'title' : 'New Title'})
3045  call assert_equal(5, g:Xgetlist({'changedtick' : 0}).changedtick)
3046
3047  enew!
3048  call append(0, ["F5:50:L50", "F6:60:L60"])
3049  Xaddbuffer
3050  call assert_equal(6, g:Xgetlist({'changedtick' : 0}).changedtick)
3051  enew!
3052
3053  call g:Xsetlist([], 'a', {'context' : {'bus' : 'pci'}})
3054  call assert_equal(7, g:Xgetlist({'changedtick' : 0}).changedtick)
3055  call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'},
3056	      \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], 'a')
3057  call assert_equal(8, g:Xgetlist({'changedtick' : 0}).changedtick)
3058  call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'},
3059	      \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], ' ')
3060  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3061  call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'},
3062	      \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], 'r')
3063  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
3064
3065  call writefile(["F8:80:L80", "F8:81:L81"], "Xone")
3066  Xfile Xone
3067  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3068  Xaddfile Xone
3069  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
3070
3071  " Test case for updating a non-current quickfix list
3072  call g:Xsetlist([], 'f')
3073  Xexpr "F1:1:L1"
3074  Xexpr "F2:2:L2"
3075  call g:Xsetlist([], 'a', {'nr' : 1, "lines" : ["F10:10:L10"]})
3076  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3077  call assert_equal(2, g:Xgetlist({'nr' : 1, 'changedtick' : 0}).changedtick)
3078
3079  call delete("Xone")
3080endfunc
3081
3082func Test_qf_tick()
3083  call Xqftick_tests('c')
3084  call Xqftick_tests('l')
3085endfunc
3086
3087" The following test used to crash Vim.
3088" Open the location list window and close the regular window associated with
3089" the location list. When the garbage collection runs now, it incorrectly
3090" marks the location list context as not in use and frees the context.
3091func Test_ll_window_ctx()
3092  call setloclist(0, [], 'f')
3093  call setloclist(0, [], 'a', {'context' : []})
3094  lopen | only
3095  call test_garbagecollect_now()
3096  echo getloclist(0, {'context' : 1}).context
3097  enew | only
3098endfunc
3099
3100" The following test used to crash vim
3101func Test_lfile_crash()
3102  sp Xtest
3103  au QuickFixCmdPre * bw
3104  call assert_fails('lfile', 'E40')
3105  au! QuickFixCmdPre
3106endfunc
3107
3108" The following test used to crash vim
3109func Test_lbuffer_crash()
3110  sv Xtest
3111  augroup QF_Test
3112    au!
3113    au * * bw
3114  augroup END
3115  lbuffer
3116  augroup QF_Test
3117    au!
3118  augroup END
3119endfunc
3120
3121" The following test used to crash vim
3122func Test_lexpr_crash()
3123  augroup QF_Test
3124    au!
3125    au * * call setloclist(0, [], 'f')
3126  augroup END
3127  lexpr ""
3128  augroup QF_Test
3129    au!
3130  augroup END
3131  enew | only
3132endfunc
3133
3134" The following test used to crash Vim
3135func Test_lvimgrep_crash()
3136  sv Xtest
3137  augroup QF_Test
3138    au!
3139    au * * call setloclist(0, [], 'f')
3140  augroup END
3141  lvimgrep quickfix test_quickfix.vim
3142  augroup QF_Test
3143    au!
3144  augroup END
3145  enew | only
3146endfunc
3147
3148" Test for the position of the quickfix and location list window
3149func Test_qfwin_pos()
3150  " Open two windows
3151  new | only
3152  new
3153  cexpr ['F1:10:L10']
3154  copen
3155  " Quickfix window should be the bottom most window
3156  call assert_equal(3, winnr())
3157  close
3158  " Open at the very top
3159  wincmd t
3160  topleft copen
3161  call assert_equal(1, winnr())
3162  close
3163  " open left of the current window
3164  wincmd t
3165  below new
3166  leftabove copen
3167  call assert_equal(2, winnr())
3168  close
3169  " open right of the current window
3170  rightbelow copen
3171  call assert_equal(3, winnr())
3172  close
3173endfunc
3174
3175" Tests for quickfix/location lists changed by autocommands when
3176" :vimgrep/:lvimgrep commands are running.
3177func Test_vimgrep_autocmd()
3178  call setqflist([], 'f')
3179  call writefile(['stars'], 'Xtest1.txt')
3180  call writefile(['stars'], 'Xtest2.txt')
3181
3182  " Test 1:
3183  " When searching for a pattern using :vimgrep, if the quickfix list is
3184  " changed by an autocmd, the results should be added to the correct quickfix
3185  " list.
3186  autocmd BufRead Xtest2.txt cexpr '' | cexpr ''
3187  silent vimgrep stars Xtest*.txt
3188  call assert_equal(1, getqflist({'nr' : 0}).nr)
3189  call assert_equal(3, getqflist({'nr' : '$'}).nr)
3190  call assert_equal('Xtest2.txt', bufname(getqflist()[1].bufnr))
3191  au! BufRead Xtest2.txt
3192
3193  " Test 2:
3194  " When searching for a pattern using :vimgrep, if the quickfix list is
3195  " freed, then a error should be given.
3196  silent! %bwipe!
3197  call setqflist([], 'f')
3198  autocmd BufRead Xtest2.txt for i in range(10) | cexpr '' | endfor
3199  call assert_fails('vimgrep stars Xtest*.txt', 'E925:')
3200  au! BufRead Xtest2.txt
3201
3202  " Test 3:
3203  " When searching for a pattern using :lvimgrep, if the location list is
3204  " freed, then the command should error out.
3205  silent! %bwipe!
3206  let g:save_winid = win_getid()
3207  autocmd BufRead Xtest2.txt call setloclist(g:save_winid, [], 'f')
3208  call assert_fails('lvimgrep stars Xtest*.txt', 'E926:')
3209  au! BufRead Xtest2.txt
3210
3211  call delete('Xtest1.txt')
3212  call delete('Xtest2.txt')
3213  call setqflist([], 'f')
3214endfunc
3215
3216" The following test used to crash Vim
3217func Test_lhelpgrep_autocmd()
3218  lhelpgrep quickfix
3219  autocmd QuickFixCmdPost * call setloclist(0, [], 'f')
3220  lhelpgrep buffer
3221  call assert_equal('help', &filetype)
3222  call assert_equal(0, getloclist(0, {'nr' : '$'}).nr)
3223  lhelpgrep tabpage
3224  call assert_equal('help', &filetype)
3225  call assert_equal(1, getloclist(0, {'nr' : '$'}).nr)
3226  au! QuickFixCmdPost
3227  new | only
3228endfunc
3229
3230" Test for shortening/simplifying the file name when opening the
3231" quickfix window or when displaying the quickfix list
3232func Test_shorten_fname()
3233  if !has('unix')
3234    return
3235  endif
3236  %bwipe
3237  " Create a quickfix list with a absolute path filename
3238  let fname = getcwd() . '/test_quickfix.vim'
3239  call setqflist([], ' ', {'lines':[fname . ":20:Line20"], 'efm':'%f:%l:%m'})
3240  call assert_equal(fname, bufname('test_quickfix.vim'))
3241  " Opening the quickfix window should simplify the file path
3242  cwindow
3243  call assert_equal('test_quickfix.vim', bufname('test_quickfix.vim'))
3244  cclose
3245  %bwipe
3246  " Create a quickfix list with a absolute path filename
3247  call setqflist([], ' ', {'lines':[fname . ":20:Line20"], 'efm':'%f:%l:%m'})
3248  call assert_equal(fname, bufname('test_quickfix.vim'))
3249  " Displaying the quickfix list should simplify the file path
3250  silent! clist
3251  call assert_equal('test_quickfix.vim', bufname('test_quickfix.vim'))
3252endfunc
3253