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