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()))
1491  call assert_fails('call g:Xsetlist([], [])', 'E928:')
1492endfunc
1493
1494func Test_setqflist()
1495  new Xtestfile | only
1496  let bnum = bufnr('%')
1497  call setline(1, range(1,5))
1498
1499  call SetXlistTests('c', bnum)
1500  call SetXlistTests('l', bnum)
1501
1502  enew!
1503  call delete('Xtestfile')
1504endfunc
1505
1506func Xlist_empty_middle(cchar)
1507  call s:setup_commands(a:cchar)
1508
1509  " create three quickfix lists
1510  let @/ = 'Test_'
1511  Xvimgrep // test_quickfix.vim
1512  let testlen = len(g:Xgetlist())
1513  call assert_true(testlen > 0)
1514  Xvimgrep empty test_quickfix.vim
1515  call assert_true(len(g:Xgetlist()) > 0)
1516  Xvimgrep matches test_quickfix.vim
1517  let matchlen = len(g:Xgetlist())
1518  call assert_true(matchlen > 0)
1519  Xolder
1520  " make the middle list empty
1521  call g:Xsetlist([], 'r')
1522  call assert_true(len(g:Xgetlist()) == 0)
1523  Xolder
1524  call assert_equal(testlen, len(g:Xgetlist()))
1525  Xnewer
1526  Xnewer
1527  call assert_equal(matchlen, len(g:Xgetlist()))
1528endfunc
1529
1530func Test_setqflist_empty_middle()
1531  call Xlist_empty_middle('c')
1532  call Xlist_empty_middle('l')
1533endfunc
1534
1535func Xlist_empty_older(cchar)
1536  call s:setup_commands(a:cchar)
1537
1538  " create three quickfix lists
1539  Xvimgrep one test_quickfix.vim
1540  let onelen = len(g:Xgetlist())
1541  call assert_true(onelen > 0)
1542  Xvimgrep two test_quickfix.vim
1543  let twolen = len(g:Xgetlist())
1544  call assert_true(twolen > 0)
1545  Xvimgrep three test_quickfix.vim
1546  let threelen = len(g:Xgetlist())
1547  call assert_true(threelen > 0)
1548  Xolder 2
1549  " make the first list empty, check the others didn't change
1550  call g:Xsetlist([], 'r')
1551  call assert_true(len(g:Xgetlist()) == 0)
1552  Xnewer
1553  call assert_equal(twolen, len(g:Xgetlist()))
1554  Xnewer
1555  call assert_equal(threelen, len(g:Xgetlist()))
1556endfunc
1557
1558func Test_setqflist_empty_older()
1559  call Xlist_empty_older('c')
1560  call Xlist_empty_older('l')
1561endfunc
1562
1563func XquickfixSetListWithAct(cchar)
1564  call s:setup_commands(a:cchar)
1565
1566  let list1 = [{'filename': 'fnameA', 'text': 'A'},
1567          \    {'filename': 'fnameB', 'text': 'B'}]
1568  let list2 = [{'filename': 'fnameC', 'text': 'C'},
1569          \    {'filename': 'fnameD', 'text': 'D'},
1570          \    {'filename': 'fnameE', 'text': 'E'}]
1571
1572  " {action} is unspecified.  Same as specifying ' '.
1573  new | only
1574  silent! Xnewer 99
1575  call g:Xsetlist(list1)
1576  call g:Xsetlist(list2)
1577  let li = g:Xgetlist()
1578  call assert_equal(3, len(li))
1579  call assert_equal('C', li[0]['text'])
1580  call assert_equal('D', li[1]['text'])
1581  call assert_equal('E', li[2]['text'])
1582  silent! Xolder
1583  let li = g:Xgetlist()
1584  call assert_equal(2, len(li))
1585  call assert_equal('A', li[0]['text'])
1586  call assert_equal('B', li[1]['text'])
1587
1588  " {action} is specified ' '.
1589  new | only
1590  silent! Xnewer 99
1591  call g:Xsetlist(list1)
1592  call g:Xsetlist(list2, ' ')
1593  let li = g:Xgetlist()
1594  call assert_equal(3, len(li))
1595  call assert_equal('C', li[0]['text'])
1596  call assert_equal('D', li[1]['text'])
1597  call assert_equal('E', li[2]['text'])
1598  silent! Xolder
1599  let li = g:Xgetlist()
1600  call assert_equal(2, len(li))
1601  call assert_equal('A', li[0]['text'])
1602  call assert_equal('B', li[1]['text'])
1603
1604  " {action} is specified 'a'.
1605  new | only
1606  silent! Xnewer 99
1607  call g:Xsetlist(list1)
1608  call g:Xsetlist(list2, 'a')
1609  let li = g:Xgetlist()
1610  call assert_equal(5, len(li))
1611  call assert_equal('A', li[0]['text'])
1612  call assert_equal('B', li[1]['text'])
1613  call assert_equal('C', li[2]['text'])
1614  call assert_equal('D', li[3]['text'])
1615  call assert_equal('E', li[4]['text'])
1616
1617  " {action} is specified 'r'.
1618  new | only
1619  silent! Xnewer 99
1620  call g:Xsetlist(list1)
1621  call g:Xsetlist(list2, 'r')
1622  let li = g:Xgetlist()
1623  call assert_equal(3, len(li))
1624  call assert_equal('C', li[0]['text'])
1625  call assert_equal('D', li[1]['text'])
1626  call assert_equal('E', li[2]['text'])
1627
1628  " Test for wrong value.
1629  new | only
1630  call assert_fails("call g:Xsetlist(0)", 'E714:')
1631  call assert_fails("call g:Xsetlist(list1, '')", 'E927:')
1632  call assert_fails("call g:Xsetlist(list1, 'aa')", 'E927:')
1633  call assert_fails("call g:Xsetlist(list1, ' a')", 'E927:')
1634  call assert_fails("call g:Xsetlist(list1, 0)", 'E928:')
1635endfunc
1636
1637func Test_setqflist_invalid_nr()
1638  " The following command used to crash Vim
1639  eval []->setqflist(' ', {'nr' : $XXX_DOES_NOT_EXIST})
1640endfunc
1641
1642func Test_setqflist_user_sets_buftype()
1643  call setqflist([{'text': 'foo'}, {'text': 'bar'}])
1644  set buftype=quickfix
1645  call setqflist([], 'a')
1646  enew
1647endfunc
1648
1649func Test_quickfix_set_list_with_act()
1650  call XquickfixSetListWithAct('c')
1651  call XquickfixSetListWithAct('l')
1652endfunc
1653
1654func XLongLinesTests(cchar)
1655  let l = g:Xgetlist()
1656
1657  call assert_equal(4, len(l))
1658  call assert_equal(1, l[0].lnum)
1659  call assert_equal(1, l[0].col)
1660  call assert_equal(1975, len(l[0].text))
1661  call assert_equal(2, l[1].lnum)
1662  call assert_equal(1, l[1].col)
1663  call assert_equal(4070, len(l[1].text))
1664  call assert_equal(3, l[2].lnum)
1665  call assert_equal(1, l[2].col)
1666  call assert_equal(4070, len(l[2].text))
1667  call assert_equal(4, l[3].lnum)
1668  call assert_equal(1, l[3].col)
1669  call assert_equal(10, len(l[3].text))
1670
1671  call g:Xsetlist([], 'r')
1672endfunc
1673
1674func s:long_lines_tests(cchar)
1675  call s:setup_commands(a:cchar)
1676
1677  let testfile = 'samples/quickfix.txt'
1678
1679  " file
1680  exe 'Xgetfile' testfile
1681  call XLongLinesTests(a:cchar)
1682
1683  " list
1684  Xexpr readfile(testfile)
1685  call XLongLinesTests(a:cchar)
1686
1687  " string
1688  Xexpr join(readfile(testfile), "\n")
1689  call XLongLinesTests(a:cchar)
1690
1691  " buffer
1692  exe 'edit' testfile
1693  exe 'Xbuffer' bufnr('%')
1694  call XLongLinesTests(a:cchar)
1695endfunc
1696
1697func Test_long_lines()
1698  call s:long_lines_tests('c')
1699  call s:long_lines_tests('l')
1700endfunc
1701
1702func s:create_test_file(filename)
1703  let l = []
1704  for i in range(1, 20)
1705      call add(l, 'Line' . i)
1706  endfor
1707  call writefile(l, a:filename)
1708endfunc
1709
1710func Test_switchbuf()
1711  CheckNotBSD
1712  call s:create_test_file('Xqftestfile1')
1713  call s:create_test_file('Xqftestfile2')
1714  call s:create_test_file('Xqftestfile3')
1715
1716  new | only
1717  edit Xqftestfile1
1718  let file1_winid = win_getid()
1719  new Xqftestfile2
1720  let file2_winid = win_getid()
1721  cgetexpr ['Xqftestfile1:5:Line5',
1722		\ 'Xqftestfile1:6:Line6',
1723		\ 'Xqftestfile2:10:Line10',
1724		\ 'Xqftestfile2:11:Line11',
1725		\ 'Xqftestfile3:15:Line15',
1726		\ 'Xqftestfile3:16:Line16']
1727
1728  new
1729  let winid = win_getid()
1730  cfirst | cnext
1731  call assert_equal(winid, win_getid())
1732  2cnext
1733  call assert_equal(winid, win_getid())
1734  2cnext
1735  call assert_equal(winid, win_getid())
1736
1737  " Test for 'switchbuf' set to search for files in windows in the current
1738  " tabpage and jump to an existing window (if present)
1739  set switchbuf=useopen
1740  enew
1741  cfirst | cnext
1742  call assert_equal(file1_winid, win_getid())
1743  2cnext
1744  call assert_equal(file2_winid, win_getid())
1745  2cnext
1746  call assert_equal(file2_winid, win_getid())
1747
1748  " Test for 'switchbuf' set to search for files in tabpages and jump to an
1749  " existing tabpage (if present)
1750  enew | only
1751  set switchbuf=usetab
1752  tabedit Xqftestfile1
1753  tabedit Xqftestfile2
1754  tabedit Xqftestfile3
1755  tabfirst
1756  cfirst | cnext
1757  call assert_equal(2, tabpagenr())
1758  2cnext
1759  call assert_equal(3, tabpagenr())
1760  6cnext
1761  call assert_equal(4, tabpagenr())
1762  2cpfile
1763  call assert_equal(2, tabpagenr())
1764  2cnfile
1765  call assert_equal(4, tabpagenr())
1766  tabfirst | tabonly | enew
1767
1768  " Test for 'switchbuf' set to open a new window for every file
1769  set switchbuf=split
1770  cfirst | cnext
1771  call assert_equal(1, winnr('$'))
1772  cnext | cnext
1773  call assert_equal(2, winnr('$'))
1774  cnext | cnext
1775  call assert_equal(3, winnr('$'))
1776
1777  " Test for 'switchbuf' set to open a new tabpage for every file
1778  set switchbuf=newtab
1779  enew | only
1780  cfirst | cnext
1781  call assert_equal(1, tabpagenr('$'))
1782  cnext | cnext
1783  call assert_equal(2, tabpagenr('$'))
1784  cnext | cnext
1785  call assert_equal(3, tabpagenr('$'))
1786  tabfirst | enew | tabonly | only
1787
1788  set switchbuf=uselast
1789  split
1790  let last_winid = win_getid()
1791  copen
1792  exe "normal 1G\<CR>"
1793  call assert_equal(last_winid, win_getid())
1794  enew | only
1795
1796  " With an empty 'switchbuf', jumping to a quickfix entry should open the
1797  " file in an existing window (if present)
1798  set switchbuf=
1799  edit Xqftestfile1
1800  let file1_winid = win_getid()
1801  new Xqftestfile2
1802  let file2_winid = win_getid()
1803  copen
1804  exe "normal 1G\<CR>"
1805  call assert_equal(file1_winid, win_getid())
1806  copen
1807  exe "normal 3G\<CR>"
1808  call assert_equal(file2_winid, win_getid())
1809  copen | only
1810  exe "normal 5G\<CR>"
1811  call assert_equal(2, winnr('$'))
1812  call assert_equal(1, bufwinnr('Xqftestfile3'))
1813
1814  " If only quickfix window is open in the current tabpage, jumping to an
1815  " entry with 'switchbuf' set to 'usetab' should search in other tabpages.
1816  enew | only
1817  set switchbuf=usetab
1818  tabedit Xqftestfile1
1819  tabedit Xqftestfile2
1820  tabedit Xqftestfile3
1821  tabfirst
1822  copen | only
1823  clast
1824  call assert_equal(4, tabpagenr())
1825  tabfirst | tabonly | enew | only
1826
1827  " Jumping to a file that is not present in any of the tabpages and the
1828  " current tabpage doesn't have any usable windows, should open it in a new
1829  " window in the current tabpage.
1830  copen | only
1831  cfirst
1832  call assert_equal(1, tabpagenr())
1833  call assert_equal('Xqftestfile1', bufname(''))
1834
1835  " If opening a file changes 'switchbuf', then the new value should be
1836  " retained.
1837  call writefile(["vim: switchbuf=split"], 'Xqftestfile1')
1838  enew | only
1839  set switchbuf&vim
1840  cexpr "Xqftestfile1:1:10"
1841  call assert_equal('split', &switchbuf)
1842  call writefile(["vim: switchbuf=usetab"], 'Xqftestfile1')
1843  enew | only
1844  set switchbuf=useopen
1845  cexpr "Xqftestfile1:1:10"
1846  call assert_equal('usetab', &switchbuf)
1847  call writefile(["vim: switchbuf&vim"], 'Xqftestfile1')
1848  enew | only
1849  set switchbuf=useopen
1850  cexpr "Xqftestfile1:1:10"
1851  call assert_equal('', &switchbuf)
1852
1853  call delete('Xqftestfile1')
1854  call delete('Xqftestfile2')
1855  call delete('Xqftestfile3')
1856  set switchbuf&vim
1857
1858  enew | only
1859endfunc
1860
1861func Xadjust_qflnum(cchar)
1862  call s:setup_commands(a:cchar)
1863
1864  enew | only
1865
1866  let fname = 'Xqftestfile' . a:cchar
1867  call s:create_test_file(fname)
1868  exe 'edit ' . fname
1869
1870  Xgetexpr [fname . ':5:Line5',
1871	      \ fname . ':10:Line10',
1872	      \ fname . ':15:Line15',
1873	      \ fname . ':20:Line20']
1874
1875  6,14delete
1876  call append(6, ['Buffer', 'Window'])
1877
1878  let l = g:Xgetlist()
1879  call assert_equal(5, l[0].lnum)
1880  call assert_equal(6, l[2].lnum)
1881  call assert_equal(13, l[3].lnum)
1882
1883  " If a file doesn't have any quickfix entries, then deleting lines in the
1884  " file should not update the quickfix list
1885  call g:Xsetlist([], 'f')
1886  1,2delete
1887  call assert_equal([], g:Xgetlist())
1888
1889  enew!
1890  call delete(fname)
1891endfunc
1892
1893func Test_adjust_lnum()
1894  call setloclist(0, [])
1895  call Xadjust_qflnum('c')
1896  call setqflist([])
1897  call Xadjust_qflnum('l')
1898endfunc
1899
1900" Tests for the :grep/:lgrep and :grepadd/:lgrepadd commands
1901func s:test_xgrep(cchar)
1902  call s:setup_commands(a:cchar)
1903
1904  " The following lines are used for the grep test. Don't remove.
1905  " Grep_Test_Text: Match 1
1906  " Grep_Test_Text: Match 2
1907  " GrepAdd_Test_Text: Match 1
1908  " GrepAdd_Test_Text: Match 2
1909  enew! | only
1910  set makeef&vim
1911  silent Xgrep Grep_Test_Text: test_quickfix.vim
1912  call assert_true(len(g:Xgetlist()) == 5)
1913  Xopen
1914  call assert_true(w:quickfix_title =~ '^:grep')
1915  Xclose
1916  enew
1917  set makeef=Temp_File_##
1918  silent Xgrepadd GrepAdd_Test_Text: test_quickfix.vim
1919  call assert_true(len(g:Xgetlist()) == 9)
1920
1921  " Try with 'grepprg' set to 'internal'
1922  set grepprg=internal
1923  silent Xgrep Grep_Test_Text: test_quickfix.vim
1924  silent Xgrepadd GrepAdd_Test_Text: test_quickfix.vim
1925  call assert_true(len(g:Xgetlist()) == 9)
1926  set grepprg&vim
1927
1928  call writefile(['Vim'], 'XtestTempFile')
1929  set makeef=XtestTempFile
1930  silent Xgrep Grep_Test_Text: test_quickfix.vim
1931  call assert_equal(5, len(g:Xgetlist()))
1932  call assert_false(filereadable('XtestTempFile'))
1933  set makeef&vim
1934endfunc
1935
1936func Test_grep()
1937  if !has('unix')
1938    " The grepprg may not be set on non-Unix systems
1939    return
1940  endif
1941
1942  call s:test_xgrep('c')
1943  call s:test_xgrep('l')
1944endfunc
1945
1946func Test_two_windows()
1947  " Use one 'errorformat' for two windows.  Add an expression to each of them,
1948  " make sure they each keep their own state.
1949  set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f'
1950  call mkdir('Xone/a', 'p')
1951  call mkdir('Xtwo/a', 'p')
1952  let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7']
1953  call writefile(lines, 'Xone/a/one.txt')
1954  call writefile(lines, 'Xtwo/a/two.txt')
1955
1956  new one
1957  let one_id = win_getid()
1958  lexpr ""
1959  new two
1960  let two_id = win_getid()
1961  lexpr ""
1962
1963  laddexpr "Entering dir 'Xtwo/a'"
1964  call win_gotoid(one_id)
1965  laddexpr "Entering dir 'Xone/a'"
1966  call win_gotoid(two_id)
1967  laddexpr 'two.txt:5:two two two'
1968  call win_gotoid(one_id)
1969  laddexpr 'one.txt:3:one one one'
1970
1971  let loc_one = getloclist(one_id)
1972  call assert_equal('Xone/a/one.txt', bufname(loc_one[1].bufnr))
1973  call assert_equal(3, loc_one[1].lnum)
1974
1975  let loc_two = getloclist(two_id)
1976  call assert_equal('Xtwo/a/two.txt', bufname(loc_two[1].bufnr))
1977  call assert_equal(5, loc_two[1].lnum)
1978
1979  call win_gotoid(one_id)
1980  bwipe!
1981  call win_gotoid(two_id)
1982  bwipe!
1983  call delete('Xone', 'rf')
1984  call delete('Xtwo', 'rf')
1985endfunc
1986
1987func XbottomTests(cchar)
1988  call s:setup_commands(a:cchar)
1989
1990  " Calling lbottom without any errors should fail
1991  if a:cchar == 'l'
1992      call assert_fails('lbottom', 'E776:')
1993  endif
1994
1995  call g:Xsetlist([{'filename': 'foo', 'lnum': 42}])
1996  Xopen
1997  let wid = win_getid()
1998  call assert_equal(1, line('.'))
1999  wincmd w
2000  call g:Xsetlist([{'filename': 'var', 'lnum': 24}], 'a')
2001  Xbottom
2002  call win_gotoid(wid)
2003  call assert_equal(2, line('.'))
2004  Xclose
2005endfunc
2006
2007" Tests for the :cbottom and :lbottom commands
2008func Test_cbottom()
2009  call XbottomTests('c')
2010  call XbottomTests('l')
2011endfunc
2012
2013func HistoryTest(cchar)
2014  call s:setup_commands(a:cchar)
2015
2016  " clear all lists after the first one, then replace the first one.
2017  call g:Xsetlist([])
2018  call assert_fails('Xolder 99', 'E380:')
2019  let entry = {'filename': 'foo', 'lnum': 42}
2020  call g:Xsetlist([entry], 'r')
2021  call g:Xsetlist([entry, entry])
2022  call g:Xsetlist([entry, entry, entry])
2023  let res = split(execute(a:cchar . 'hist'), "\n")
2024  call assert_equal(3, len(res))
2025  let common = 'errors     :set' . (a:cchar == 'c' ? 'qf' : 'loc') . 'list()'
2026  call assert_equal('  error list 1 of 3; 1 ' . common, res[0])
2027  call assert_equal('  error list 2 of 3; 2 ' . common, res[1])
2028  call assert_equal('> error list 3 of 3; 3 ' . common, res[2])
2029
2030  " Test for changing the quickfix lists
2031  call assert_equal(3, g:Xgetlist({'nr' : 0}).nr)
2032  exe '1' . a:cchar . 'hist'
2033  call assert_equal(1, g:Xgetlist({'nr' : 0}).nr)
2034  exe '3' . a:cchar . 'hist'
2035  call assert_equal(3, g:Xgetlist({'nr' : 0}).nr)
2036  call assert_fails('-2' . a:cchar . 'hist', 'E16:')
2037  call assert_fails('4' . a:cchar . 'hist', 'E16:')
2038
2039  call g:Xsetlist([], 'f')
2040  let l = split(execute(a:cchar . 'hist'), "\n")
2041  call assert_equal('No entries', l[0])
2042  if a:cchar == 'c'
2043    call assert_fails('4chist', 'E16:')
2044  else
2045    call assert_fails('4lhist', 'E776:')
2046  endif
2047
2048  " An empty list should still show the stack history
2049  call g:Xsetlist([])
2050  let res = split(execute(a:cchar . 'hist'), "\n")
2051  call assert_equal('> error list 1 of 1; 0 ' . common, res[0])
2052
2053  call g:Xsetlist([], 'f')
2054endfunc
2055
2056func Test_history()
2057  call HistoryTest('c')
2058  call HistoryTest('l')
2059endfunc
2060
2061func Test_duplicate_buf()
2062  " make sure we can get the highest buffer number
2063  edit DoesNotExist
2064  edit DoesNotExist2
2065  let last_buffer = bufnr("$")
2066
2067  " make sure only one buffer is created
2068  call writefile(['this one', 'that one'], 'Xgrepthis')
2069  vimgrep one Xgrepthis
2070  vimgrep one Xgrepthis
2071  call assert_equal(last_buffer + 1, bufnr("$"))
2072
2073  call delete('Xgrepthis')
2074endfunc
2075
2076" Quickfix/Location list set/get properties tests
2077func Xproperty_tests(cchar)
2078    call s:setup_commands(a:cchar)
2079
2080    " Error cases
2081    call assert_fails('call g:Xgetlist(99)', 'E715:')
2082    call assert_fails('call g:Xsetlist(99)', 'E714:')
2083    call assert_fails('call g:Xsetlist([], "a", [])', 'E715:')
2084
2085    " Set and get the title
2086    call g:Xsetlist([])
2087    Xopen
2088    wincmd p
2089    call g:Xsetlist([{'filename':'foo', 'lnum':27}])
2090    let s = g:Xsetlist([], 'a', {'title' : 'Sample'})
2091    call assert_equal(0, s)
2092    let d = g:Xgetlist({"title":1})
2093    call assert_equal('Sample', d.title)
2094    " Try setting title to a non-string value
2095    call assert_equal(-1, g:Xsetlist([], 'a', {'title' : ['Test']}))
2096    call assert_equal('Sample', g:Xgetlist({"title":1}).title)
2097
2098    Xopen
2099    call assert_equal('Sample', w:quickfix_title)
2100    Xclose
2101
2102    " Tests for action argument
2103    silent! Xolder 999
2104    let qfnr = g:Xgetlist({'all':1}).nr
2105    call g:Xsetlist([], 'r', {'title' : 'N1'})
2106    call assert_equal('N1', g:Xgetlist({'all':1}).title)
2107    call g:Xsetlist([], ' ', {'title' : 'N2'})
2108    call assert_equal(qfnr + 1, g:Xgetlist({'all':1}).nr)
2109
2110    let res = g:Xgetlist({'nr': 0})
2111    call assert_equal(qfnr + 1, res.nr)
2112    call assert_equal(['nr'], keys(res))
2113
2114    call g:Xsetlist([], ' ', {'title' : 'N3'})
2115    call assert_equal('N2', g:Xgetlist({'nr':2, 'title':1}).title)
2116
2117    " Changing the title of an earlier quickfix list
2118    call g:Xsetlist([], 'r', {'title' : 'NewTitle', 'nr' : 2})
2119    call assert_equal('NewTitle', g:Xgetlist({'nr':2, 'title':1}).title)
2120
2121    " Changing the title of an invalid quickfix list
2122    call assert_equal(-1, g:Xsetlist([], ' ',
2123		\ {'title' : 'SomeTitle', 'nr' : 99}))
2124    call assert_equal(-1, g:Xsetlist([], ' ',
2125		\ {'title' : 'SomeTitle', 'nr' : 'abc'}))
2126
2127    if a:cchar == 'c'
2128	copen
2129	call assert_equal({'winid':win_getid()}, getqflist({'winid':1}))
2130	cclose
2131    endif
2132
2133    " Invalid arguments
2134    call assert_fails('call g:Xgetlist([])', 'E715')
2135    call assert_fails('call g:Xsetlist([], "a", [])', 'E715')
2136    let s = g:Xsetlist([], 'a', {'abc':1})
2137    call assert_equal(-1, s)
2138
2139    call assert_equal({}, g:Xgetlist({'abc':1}))
2140    call assert_equal('', g:Xgetlist({'nr':99, 'title':1}).title)
2141    call assert_equal('', g:Xgetlist({'nr':[], 'title':1}).title)
2142
2143    if a:cchar == 'l'
2144	call assert_equal({}, getloclist(99, {'title': 1}))
2145    endif
2146
2147    " Context related tests
2148    let s = g:Xsetlist([], 'a', {'context':[1,2,3]})
2149    call assert_equal(0, s)
2150    call test_garbagecollect_now()
2151    let d = g:Xgetlist({'context':1})
2152    call assert_equal([1,2,3], d.context)
2153    call g:Xsetlist([], 'a', {'context':{'color':'green'}})
2154    let d = g:Xgetlist({'context':1})
2155    call assert_equal({'color':'green'}, d.context)
2156    call g:Xsetlist([], 'a', {'context':"Context info"})
2157    let d = g:Xgetlist({'context':1})
2158    call assert_equal("Context info", d.context)
2159    call g:Xsetlist([], 'a', {'context':246})
2160    let d = g:Xgetlist({'context':1})
2161    call assert_equal(246, d.context)
2162    " set other Vim data types as context
2163    call g:Xsetlist([], 'a', {'context' : test_null_blob()})
2164    if has('channel')
2165      call g:Xsetlist([], 'a', {'context' : test_null_channel()})
2166    endif
2167    if has('job')
2168      call g:Xsetlist([], 'a', {'context' : test_null_job()})
2169    endif
2170    call g:Xsetlist([], 'a', {'context' : test_null_function()})
2171    call g:Xsetlist([], 'a', {'context' : test_null_partial()})
2172    call g:Xsetlist([], 'a', {'context' : ''})
2173    call test_garbagecollect_now()
2174    if a:cchar == 'l'
2175	" Test for copying context across two different location lists
2176	new | only
2177	let w1_id = win_getid()
2178	let l = [1]
2179	call setloclist(0, [], 'a', {'context':l})
2180	new
2181	let w2_id = win_getid()
2182	call add(l, 2)
2183	call assert_equal([1, 2], getloclist(w1_id, {'context':1}).context)
2184	call assert_equal([1, 2], getloclist(w2_id, {'context':1}).context)
2185	unlet! l
2186	call assert_equal([1, 2], getloclist(w2_id, {'context':1}).context)
2187	only
2188	call setloclist(0, [], 'f')
2189	call assert_equal('', getloclist(0, {'context':1}).context)
2190    endif
2191
2192    " Test for changing the context of previous quickfix lists
2193    call g:Xsetlist([], 'f')
2194    Xexpr "One"
2195    Xexpr "Two"
2196    Xexpr "Three"
2197    call g:Xsetlist([], 'r', {'context' : [1], 'nr' : 1})
2198    call g:Xsetlist([], 'a', {'context' : [2], 'nr' : 2})
2199    " Also, check for setting the context using quickfix list number zero.
2200    call g:Xsetlist([], 'r', {'context' : [3], 'nr' : 0})
2201    call test_garbagecollect_now()
2202    let l = g:Xgetlist({'nr' : 1, 'context' : 1})
2203    call assert_equal([1], l.context)
2204    let l = g:Xgetlist({'nr' : 2, 'context' : 1})
2205    call assert_equal([2], l.context)
2206    let l = g:Xgetlist({'nr' : 3, 'context' : 1})
2207    call assert_equal([3], l.context)
2208
2209    " Test for changing the context through reference and for garbage
2210    " collection of quickfix context
2211    let l = ["red"]
2212    call g:Xsetlist([], ' ', {'context' : l})
2213    call add(l, "blue")
2214    let x = g:Xgetlist({'context' : 1})
2215    call add(x.context, "green")
2216    call assert_equal(["red", "blue", "green"], l)
2217    call assert_equal(["red", "blue", "green"], x.context)
2218    unlet l
2219    call test_garbagecollect_now()
2220    let m = g:Xgetlist({'context' : 1})
2221    call assert_equal(["red", "blue", "green"], m.context)
2222
2223    " Test for setting/getting items
2224    Xexpr ""
2225    let qfprev = g:Xgetlist({'nr':0})
2226    let s = g:Xsetlist([], ' ', {'title':'Green',
2227		\ 'items' : [{'filename':'F1', 'lnum':10}]})
2228    call assert_equal(0, s)
2229    let qfcur = g:Xgetlist({'nr':0})
2230    call assert_true(qfcur.nr == qfprev.nr + 1)
2231    let l = g:Xgetlist({'items':1})
2232    call assert_equal('F1', bufname(l.items[0].bufnr))
2233    call assert_equal(10, l.items[0].lnum)
2234    call g:Xsetlist([], 'a', {'items' : [{'filename':'F2', 'lnum':20},
2235		\  {'filename':'F2', 'lnum':30}]})
2236    let l = g:Xgetlist({'items':1})
2237    call assert_equal('F2', bufname(l.items[2].bufnr))
2238    call assert_equal(30, l.items[2].lnum)
2239    call g:Xsetlist([], 'r', {'items' : [{'filename':'F3', 'lnum':40}]})
2240    let l = g:Xgetlist({'items':1})
2241    call assert_equal('F3', bufname(l.items[0].bufnr))
2242    call assert_equal(40, l.items[0].lnum)
2243    call g:Xsetlist([], 'r', {'items' : []})
2244    let l = g:Xgetlist({'items':1})
2245    call assert_equal(0, len(l.items))
2246
2247    call g:Xsetlist([], 'r', {'title' : 'TestTitle'})
2248    call g:Xsetlist([], 'r', {'items' : [{'filename' : 'F1', 'lnum' : 10, 'text' : 'L10'}]})
2249    call g:Xsetlist([], 'r', {'items' : [{'filename' : 'F1', 'lnum' : 10, 'text' : 'L10'}]})
2250    call assert_equal('TestTitle', g:Xgetlist({'title' : 1}).title)
2251
2252    " Test for getting id of window associated with a location list window
2253    if a:cchar == 'l'
2254      only
2255      call assert_equal(0, g:Xgetlist({'all' : 1}).filewinid)
2256      let wid = win_getid()
2257      Xopen
2258      call assert_equal(wid, g:Xgetlist({'filewinid' : 1}).filewinid)
2259      wincmd w
2260      call assert_equal(0, g:Xgetlist({'filewinid' : 1}).filewinid)
2261      only
2262    endif
2263
2264    " The following used to crash Vim with address sanitizer
2265    call g:Xsetlist([], 'f')
2266    call g:Xsetlist([], 'a', {'items' : [{'filename':'F1', 'lnum':10}]})
2267    call assert_equal(10, g:Xgetlist({'items':1}).items[0].lnum)
2268
2269    " Try setting the items using a string
2270    call assert_equal(-1, g:Xsetlist([], ' ', {'items' : 'Test'}))
2271
2272    " Save and restore the quickfix stack
2273    call g:Xsetlist([], 'f')
2274    call assert_equal(0, g:Xgetlist({'nr':'$'}).nr)
2275    Xexpr "File1:10:Line1"
2276    Xexpr "File2:20:Line2"
2277    Xexpr "File3:30:Line3"
2278    let last_qf = g:Xgetlist({'nr':'$'}).nr
2279    call assert_equal(3, last_qf)
2280    let qstack = []
2281    for i in range(1, last_qf)
2282	let qstack = add(qstack, g:Xgetlist({'nr':i, 'all':1}))
2283    endfor
2284    call g:Xsetlist([], 'f')
2285    for i in range(len(qstack))
2286	call g:Xsetlist([], ' ', qstack[i])
2287    endfor
2288    call assert_equal(3, g:Xgetlist({'nr':'$'}).nr)
2289    call assert_equal(10, g:Xgetlist({'nr':1, 'items':1}).items[0].lnum)
2290    call assert_equal(20, g:Xgetlist({'nr':2, 'items':1}).items[0].lnum)
2291    call assert_equal(30, g:Xgetlist({'nr':3, 'items':1}).items[0].lnum)
2292    call g:Xsetlist([], 'f')
2293
2294    " Swap two quickfix lists
2295    Xexpr "File1:10:Line10"
2296    Xexpr "File2:20:Line20"
2297    Xexpr "File3:30:Line30"
2298    call g:Xsetlist([], 'r', {'nr':1,'title':'Colors','context':['Colors']})
2299    call g:Xsetlist([], 'r', {'nr':2,'title':'Fruits','context':['Fruits']})
2300    let l1=g:Xgetlist({'nr':1,'all':1})
2301    let l2=g:Xgetlist({'nr':2,'all':1})
2302    let save_id = l1.id
2303    let l1.id=l2.id
2304    let l2.id=save_id
2305    call g:Xsetlist([], 'r', l1)
2306    call g:Xsetlist([], 'r', l2)
2307    let newl1=g:Xgetlist({'nr':1,'all':1})
2308    let newl2=g:Xgetlist({'nr':2,'all':1})
2309    call assert_equal('Fruits', newl1.title)
2310    call assert_equal(['Fruits'], newl1.context)
2311    call assert_equal('Line20', newl1.items[0].text)
2312    call assert_equal('Colors', newl2.title)
2313    call assert_equal(['Colors'], newl2.context)
2314    call assert_equal('Line10', newl2.items[0].text)
2315    call g:Xsetlist([], 'f')
2316endfunc
2317
2318func Test_qf_property()
2319    call Xproperty_tests('c')
2320    call Xproperty_tests('l')
2321endfunc
2322
2323" Test for setting the current index in the location/quickfix list
2324func Xtest_setqfidx(cchar)
2325  call s:setup_commands(a:cchar)
2326
2327  Xgetexpr "F1:10:1:Line1\nF2:20:2:Line2\nF3:30:3:Line3"
2328  Xgetexpr "F4:10:1:Line1\nF5:20:2:Line2\nF6:30:3:Line3"
2329  Xgetexpr "F7:10:1:Line1\nF8:20:2:Line2\nF9:30:3:Line3"
2330
2331  call g:Xsetlist([], 'a', {'nr' : 3, 'idx' : 2})
2332  call g:Xsetlist([], 'a', {'nr' : 2, 'idx' : 2})
2333  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 3})
2334  Xolder 2
2335  Xopen
2336  call assert_equal(3, line('.'))
2337  Xnewer
2338  call assert_equal(2, line('.'))
2339  Xnewer
2340  call assert_equal(2, line('.'))
2341  " Update the current index with the quickfix window open
2342  wincmd w
2343  call g:Xsetlist([], 'a', {'nr' : 3, 'idx' : 3})
2344  Xopen
2345  call assert_equal(3, line('.'))
2346  Xclose
2347
2348  " Set the current index to the last entry
2349  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : '$'})
2350  call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx)
2351  " A large value should set the index to the last index
2352  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 1})
2353  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 999})
2354  call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx)
2355  " Invalid index values
2356  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : -1})
2357  call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx)
2358  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 0})
2359  call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx)
2360  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 'xx'})
2361  call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx)
2362  call assert_fails("call g:Xsetlist([], 'a', {'nr':1, 'idx':[]})", 'E745:')
2363
2364  call g:Xsetlist([], 'f')
2365  new | only
2366endfunc
2367
2368func Test_setqfidx()
2369  call Xtest_setqfidx('c')
2370  call Xtest_setqfidx('l')
2371endfunc
2372
2373" Tests for the QuickFixCmdPre/QuickFixCmdPost autocommands
2374func QfAutoCmdHandler(loc, cmd)
2375  call add(g:acmds, a:loc . a:cmd)
2376endfunc
2377
2378func Test_Autocmd()
2379  autocmd QuickFixCmdPre * call QfAutoCmdHandler('pre', expand('<amatch>'))
2380  autocmd QuickFixCmdPost * call QfAutoCmdHandler('post', expand('<amatch>'))
2381
2382  let g:acmds = []
2383  cexpr "F1:10:Line 10"
2384  caddexpr "F1:20:Line 20"
2385  cgetexpr "F1:30:Line 30"
2386  cexpr ""
2387  caddexpr ""
2388  cgetexpr ""
2389  silent! cexpr non_existing_func()
2390  silent! caddexpr non_existing_func()
2391  silent! cgetexpr non_existing_func()
2392  let l = ['precexpr',
2393	      \ 'postcexpr',
2394	      \ 'precaddexpr',
2395	      \ 'postcaddexpr',
2396	      \ 'precgetexpr',
2397	      \ 'postcgetexpr',
2398	      \ 'precexpr',
2399	      \ 'postcexpr',
2400	      \ 'precaddexpr',
2401	      \ 'postcaddexpr',
2402	      \ 'precgetexpr',
2403	      \ 'postcgetexpr',
2404	      \ 'precexpr',
2405	      \ 'precaddexpr',
2406	      \ 'precgetexpr']
2407  call assert_equal(l, g:acmds)
2408
2409  let g:acmds = []
2410  enew! | call append(0, "F2:10:Line 10")
2411  cbuffer!
2412  enew! | call append(0, "F2:20:Line 20")
2413  cgetbuffer
2414  enew! | call append(0, "F2:30:Line 30")
2415  caddbuffer
2416  new
2417  let bnum = bufnr('%')
2418  bunload
2419  exe 'silent! cbuffer! ' . bnum
2420  exe 'silent! cgetbuffer ' . bnum
2421  exe 'silent! caddbuffer ' . bnum
2422  enew!
2423  let l = ['precbuffer',
2424	      \ 'postcbuffer',
2425	      \ 'precgetbuffer',
2426	      \ 'postcgetbuffer',
2427	      \ 'precaddbuffer',
2428	      \ 'postcaddbuffer',
2429	      \ 'precbuffer',
2430	      \ 'precgetbuffer',
2431	      \ 'precaddbuffer']
2432  call assert_equal(l, g:acmds)
2433
2434  call writefile(['Xtest:1:Line1'], 'Xtest')
2435  call writefile([], 'Xempty')
2436  let g:acmds = []
2437  cfile Xtest
2438  caddfile Xtest
2439  cgetfile Xtest
2440  cfile Xempty
2441  caddfile Xempty
2442  cgetfile Xempty
2443  silent! cfile do_not_exist
2444  silent! caddfile do_not_exist
2445  silent! cgetfile do_not_exist
2446  let l = ['precfile',
2447	      \ 'postcfile',
2448	      \ 'precaddfile',
2449	      \ 'postcaddfile',
2450	      \ 'precgetfile',
2451	      \ 'postcgetfile',
2452	      \ 'precfile',
2453	      \ 'postcfile',
2454	      \ 'precaddfile',
2455	      \ 'postcaddfile',
2456	      \ 'precgetfile',
2457	      \ 'postcgetfile',
2458	      \ 'precfile',
2459	      \ 'postcfile',
2460	      \ 'precaddfile',
2461	      \ 'postcaddfile',
2462	      \ 'precgetfile',
2463	      \ 'postcgetfile']
2464  call assert_equal(l, g:acmds)
2465
2466  let g:acmds = []
2467  helpgrep quickfix
2468  silent! helpgrep non_existing_help_topic
2469  vimgrep test Xtest
2470  vimgrepadd test Xtest
2471  silent! vimgrep non_existing_test Xtest
2472  silent! vimgrepadd non_existing_test Xtest
2473  set makeprg=
2474  silent! make
2475  set makeprg&
2476  let l = ['prehelpgrep',
2477	      \ 'posthelpgrep',
2478	      \ 'prehelpgrep',
2479	      \ 'posthelpgrep',
2480	      \ 'previmgrep',
2481	      \ 'postvimgrep',
2482	      \ 'previmgrepadd',
2483	      \ 'postvimgrepadd',
2484	      \ 'previmgrep',
2485	      \ 'postvimgrep',
2486	      \ 'previmgrepadd',
2487	      \ 'postvimgrepadd',
2488	      \ 'premake',
2489	      \ 'postmake']
2490  call assert_equal(l, g:acmds)
2491
2492  if has('unix')
2493    " Run this test only on Unix-like systems. The grepprg may not be set on
2494    " non-Unix systems.
2495    " The following lines are used for the grep test. Don't remove.
2496    " Grep_Autocmd_Text: Match 1
2497    " GrepAdd_Autocmd_Text: Match 2
2498    let g:acmds = []
2499    silent grep Grep_Autocmd_Text test_quickfix.vim
2500    silent grepadd GrepAdd_Autocmd_Text test_quickfix.vim
2501    silent grep abc123def Xtest
2502    silent grepadd abc123def Xtest
2503    set grepprg=internal
2504    silent grep Grep_Autocmd_Text test_quickfix.vim
2505    silent grepadd GrepAdd_Autocmd_Text test_quickfix.vim
2506    silent lgrep Grep_Autocmd_Text test_quickfix.vim
2507    silent lgrepadd GrepAdd_Autocmd_Text test_quickfix.vim
2508    set grepprg&vim
2509    let l = ['pregrep',
2510		\ 'postgrep',
2511		\ 'pregrepadd',
2512		\ 'postgrepadd',
2513		\ 'pregrep',
2514		\ 'postgrep',
2515		\ 'pregrepadd',
2516		\ 'postgrepadd',
2517		\ 'pregrep',
2518		\ 'postgrep',
2519		\ 'pregrepadd',
2520		\ 'postgrepadd',
2521		\ 'prelgrep',
2522		\ 'postlgrep',
2523		\ 'prelgrepadd',
2524		\ 'postlgrepadd']
2525    call assert_equal(l, g:acmds)
2526  endif
2527
2528  call delete('Xtest')
2529  call delete('Xempty')
2530  au! QuickFixCmdPre
2531  au! QuickFixCmdPost
2532endfunc
2533
2534func Test_Autocmd_Exception()
2535  set efm=%m
2536  lgetexpr '?'
2537
2538  try
2539    call DoesNotExit()
2540  catch
2541    lgetexpr '1'
2542  finally
2543    lgetexpr '1'
2544  endtry
2545
2546  call assert_equal('1', getloclist(0)[0].text)
2547
2548  set efm&vim
2549endfunc
2550
2551func Test_caddbuffer_wrong()
2552  " This used to cause a memory access in freed memory.
2553  let save_efm = &efm
2554  set efm=%EEEE%m,%WWWW,%+CCCC%>%#,%GGGG%.#
2555  cgetexpr ['WWWW', 'EEEE', 'CCCC']
2556  let &efm = save_efm
2557  caddbuffer
2558  bwipe!
2559endfunc
2560
2561func Test_caddexpr_wrong()
2562  " This used to cause a memory access in freed memory.
2563  cbuffer
2564  cbuffer
2565  copen
2566  let save_efm = &efm
2567  set efm=%
2568  call assert_fails('caddexpr ""', 'E376:')
2569  let &efm = save_efm
2570endfunc
2571
2572func Test_dirstack_cleanup()
2573  " This used to cause a memory access in freed memory.
2574  let save_efm = &efm
2575  lexpr '0'
2576  lopen
2577  fun X(c)
2578    let save_efm=&efm
2579    set efm=%D%f
2580    if a:c == 'c'
2581      caddexpr '::'
2582    else
2583      laddexpr ':0:0'
2584    endif
2585    let &efm=save_efm
2586  endfun
2587  call X('c')
2588  call X('l')
2589  call setqflist([], 'r')
2590  caddbuffer
2591  let &efm = save_efm
2592endfunc
2593
2594" Tests for jumping to entries from the location list window and quickfix
2595" window
2596func Test_cwindow_jump()
2597  set efm=%f%%%l%%%m
2598  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2599  lopen | only
2600  lfirst
2601  call assert_true(winnr('$') == 2)
2602  call assert_true(winnr() == 1)
2603  " Location list for the new window should be set
2604  call assert_true(getloclist(0)[2].text == 'Line 30')
2605
2606  " Open a scratch buffer
2607  " Open a new window and create a location list
2608  " Open the location list window and close the other window
2609  " Jump to an entry.
2610  " Should create a new window and jump to the entry. The scratch buffer
2611  " should not be used.
2612  enew | only
2613  set buftype=nofile
2614  below new
2615  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2616  lopen
2617  2wincmd c
2618  lnext
2619  call assert_true(winnr('$') == 3)
2620  call assert_true(winnr() == 2)
2621
2622  " Open two windows with two different location lists
2623  " Open the location list window and close the previous window
2624  " Jump to an entry in the location list window
2625  " Should open the file in the first window and not set the location list.
2626  enew | only
2627  lgetexpr ["F1%5%Line 5"]
2628  below new
2629  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2630  lopen
2631  2wincmd c
2632  lnext
2633  call assert_true(winnr() == 1)
2634  call assert_true(getloclist(0)[0].text == 'Line 5')
2635
2636  enew | only
2637  cgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2638  copen
2639  cnext
2640  call assert_true(winnr('$') == 2)
2641  call assert_true(winnr() == 1)
2642
2643  " open the quickfix buffer in two windows and jump to an entry. Should open
2644  " the file in the first quickfix window.
2645  enew | only
2646  copen
2647  let bnum = bufnr('')
2648  exe 'sbuffer ' . bnum
2649  wincmd b
2650  cfirst
2651  call assert_equal(2, winnr())
2652  call assert_equal('F1', bufname(''))
2653  enew | only
2654  exe 'sb' bnum
2655  exe 'botright sb' bnum
2656  wincmd t
2657  clast
2658  call assert_equal(2, winnr())
2659  call assert_equal('quickfix', getwinvar(1, '&buftype'))
2660  call assert_equal('quickfix', getwinvar(3, '&buftype'))
2661
2662  " Jumping to a file from the location list window should find a usable
2663  " window by wrapping around the window list.
2664  enew | only
2665  call setloclist(0, [], 'f')
2666  new | new
2667  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2668  lopen
2669  1close
2670  call assert_equal(0, getloclist(3, {'id' : 0}).id)
2671  lnext
2672  call assert_equal(3, winnr())
2673  call assert_equal(getloclist(1, {'id' : 0}).id, getloclist(3, {'id' : 0}).id)
2674
2675  enew | only
2676  set efm&vim
2677endfunc
2678
2679func Test_cwindow_highlight()
2680  CheckScreendump
2681
2682  let lines =<< trim END
2683	set t_u7=
2684	call setline(1, ['some', 'text', 'with', 'matches'])
2685	write XCwindow
2686	vimgrep e XCwindow
2687	redraw
2688	cwindow 4
2689  END
2690  call writefile(lines, 'XtestCwindow')
2691  let buf = RunVimInTerminal('-S XtestCwindow', #{rows: 12})
2692  call VerifyScreenDump(buf, 'Test_quickfix_cwindow_1', {})
2693
2694  call term_sendkeys(buf, ":cnext\<CR>")
2695  call VerifyScreenDump(buf, 'Test_quickfix_cwindow_2', {})
2696
2697  " clean up
2698  call StopVimInTerminal(buf)
2699  call delete('XtestCwindow')
2700  call delete('XCwindow')
2701endfunc
2702
2703func XvimgrepTests(cchar)
2704  call s:setup_commands(a:cchar)
2705
2706  call writefile(['Editor:VIM vim',
2707	      \ 'Editor:Emacs EmAcS',
2708	      \ 'Editor:Notepad NOTEPAD'], 'Xtestfile1')
2709  call writefile(['Linux', 'MacOS', 'MS-Windows'], 'Xtestfile2')
2710
2711  " Error cases
2712  call assert_fails('Xvimgrep /abc *', 'E682:')
2713
2714  let @/=''
2715  call assert_fails('Xvimgrep // *', 'E35:')
2716
2717  call assert_fails('Xvimgrep abc', 'E683:')
2718  call assert_fails('Xvimgrep a1b2c3 Xtestfile1', 'E480:')
2719  call assert_fails('Xvimgrep pat Xa1b2c3', 'E480:')
2720
2721  Xexpr ""
2722  Xvimgrepadd Notepad Xtestfile1
2723  Xvimgrepadd MacOS Xtestfile2
2724  let l = g:Xgetlist()
2725  call assert_equal(2, len(l))
2726  call assert_equal('Editor:Notepad NOTEPAD', l[0].text)
2727
2728  10Xvimgrep #\cvim#g Xtestfile?
2729  let l = g:Xgetlist()
2730  call assert_equal(2, len(l))
2731  call assert_equal(8, l[0].col)
2732  call assert_equal(12, l[1].col)
2733
2734  1Xvimgrep ?Editor? Xtestfile*
2735  let l = g:Xgetlist()
2736  call assert_equal(1, len(l))
2737  call assert_equal('Editor:VIM vim', l[0].text)
2738
2739  edit +3 Xtestfile2
2740  Xvimgrep +\cemacs+j Xtestfile1
2741  let l = g:Xgetlist()
2742  call assert_equal('Xtestfile2', bufname(''))
2743  call assert_equal('Editor:Emacs EmAcS', l[0].text)
2744
2745  " Test for unloading a buffer after vimgrep searched the buffer
2746  %bwipe
2747  Xvimgrep /Editor/j Xtestfile*
2748  call assert_equal(0, getbufinfo('Xtestfile1')[0].loaded)
2749  call assert_equal([], getbufinfo('Xtestfile2'))
2750
2751  call delete('Xtestfile1')
2752  call delete('Xtestfile2')
2753endfunc
2754
2755" Tests for the :vimgrep command
2756func Test_vimgrep()
2757  call XvimgrepTests('c')
2758  call XvimgrepTests('l')
2759endfunc
2760
2761" Test for incsearch highlighting of the :vimgrep pattern
2762" This test used to cause "E315: ml_get: invalid lnum" errors.
2763func Test_vimgrep_incsearch()
2764  enew
2765  set incsearch
2766  call test_override("char_avail", 1)
2767
2768  call feedkeys(":2vimgrep assert test_quickfix.vim test_cdo.vim\<CR>", "ntx")
2769  let l = getqflist()
2770  call assert_equal(2, len(l))
2771
2772  call test_override("ALL", 0)
2773  set noincsearch
2774endfunc
2775
2776" Test vimgrep with the last search pattern not set
2777func Test_vimgrep_with_no_last_search_pat()
2778  let lines =<< trim [SCRIPT]
2779    call assert_fails('vimgrep // *', 'E35:')
2780    call writefile(v:errors, 'Xresult')
2781    qall!
2782  [SCRIPT]
2783  call writefile(lines, 'Xscript')
2784  if RunVim([], [], '--clean -S Xscript')
2785    call assert_equal([], readfile('Xresult'))
2786  endif
2787  call delete('Xscript')
2788  call delete('Xresult')
2789endfunc
2790
2791func XfreeTests(cchar)
2792  call s:setup_commands(a:cchar)
2793
2794  enew | only
2795
2796  " Deleting the quickfix stack should work even When the current list is
2797  " somewhere in the middle of the stack
2798  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2799  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2800  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2801  Xolder
2802  call g:Xsetlist([], 'f')
2803  call assert_equal(0, len(g:Xgetlist()))
2804
2805  " After deleting the stack, adding a new list should create a stack with a
2806  " single list.
2807  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2808  call assert_equal(1, g:Xgetlist({'all':1}).nr)
2809
2810  " Deleting the stack from a quickfix window should update/clear the
2811  " quickfix/location list window.
2812  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2813  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2814  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2815  Xolder
2816  Xwindow
2817  call g:Xsetlist([], 'f')
2818  call assert_equal(2, winnr('$'))
2819  call assert_equal(1, line('$'))
2820  Xclose
2821
2822  " Deleting the stack from a non-quickfix window should update/clear the
2823  " quickfix/location list window.
2824  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2825  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2826  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2827  Xolder
2828  Xwindow
2829  wincmd p
2830  call g:Xsetlist([], 'f')
2831  call assert_equal(0, len(g:Xgetlist()))
2832  wincmd p
2833  call assert_equal(2, winnr('$'))
2834  call assert_equal(1, line('$'))
2835
2836  " After deleting the location list stack, if the location list window is
2837  " opened, then a new location list should be created. So opening the
2838  " location list window again should not create a new window.
2839  if a:cchar == 'l'
2840      lexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2841      wincmd p
2842      lopen
2843      call assert_equal(2, winnr('$'))
2844  endif
2845  Xclose
2846endfunc
2847
2848" Tests for the quickfix free functionality
2849func Test_qf_free()
2850  call XfreeTests('c')
2851  call XfreeTests('l')
2852endfunc
2853
2854" Test for buffer overflow when parsing lines and adding new entries to
2855" the quickfix list.
2856func Test_bufoverflow()
2857  set efm=%f:%l:%m
2858  cgetexpr ['File1:100:' . repeat('x', 1025)]
2859
2860  set efm=%+GCompiler:\ %.%#,%f:%l:%m
2861  cgetexpr ['Compiler: ' . repeat('a', 1015), 'File1:10:Hello World']
2862
2863  set efm=%DEntering\ directory\ %f,%f:%l:%m
2864  cgetexpr ['Entering directory ' . repeat('a', 1006),
2865	      \ 'File1:10:Hello World']
2866  set efm&vim
2867endfunc
2868
2869" Tests for getting the quickfix stack size
2870func XsizeTests(cchar)
2871  call s:setup_commands(a:cchar)
2872
2873  call g:Xsetlist([], 'f')
2874  call assert_equal(0, g:Xgetlist({'nr':'$'}).nr)
2875  call assert_equal('', g:Xgetlist({'nr':'$', 'all':1}).title)
2876  call assert_equal(0, g:Xgetlist({'nr':0}).nr)
2877
2878  Xexpr "File1:10:Line1"
2879  Xexpr "File2:20:Line2"
2880  Xexpr "File3:30:Line3"
2881  Xolder | Xolder
2882  call assert_equal(3, g:Xgetlist({'nr':'$'}).nr)
2883  call g:Xsetlist([], 'f')
2884
2885  Xexpr "File1:10:Line1"
2886  Xexpr "File2:20:Line2"
2887  Xexpr "File3:30:Line3"
2888  Xolder | Xolder
2889  call g:Xsetlist([], 'a', {'nr':'$', 'title':'Compiler'})
2890  call assert_equal('Compiler', g:Xgetlist({'nr':3, 'all':1}).title)
2891endfunc
2892
2893func Test_Qf_Size()
2894  call XsizeTests('c')
2895  call XsizeTests('l')
2896endfunc
2897
2898func Test_cclose_from_copen()
2899    augroup QF_Test
2900	au!
2901        au FileType qf :call assert_fails(':cclose', 'E788')
2902    augroup END
2903    copen
2904    augroup QF_Test
2905	au!
2906    augroup END
2907    augroup! QF_Test
2908endfunc
2909
2910func Test_cclose_in_autocmd()
2911  " Problem is only triggered if "starting" is zero, so that the OptionsSet
2912  " event will be triggered.
2913  call test_override('starting', 1)
2914  augroup QF_Test
2915    au!
2916    au FileType qf :call assert_fails(':cclose', 'E788')
2917  augroup END
2918  copen
2919  augroup QF_Test
2920    au!
2921  augroup END
2922  augroup! QF_Test
2923  call test_override('starting', 0)
2924endfunc
2925
2926" Check that ":file" without an argument is possible even when "curbuf_lock"
2927" is set.
2928func Test_file_from_copen()
2929  " Works without argument.
2930  augroup QF_Test
2931    au!
2932    au FileType qf file
2933  augroup END
2934  copen
2935
2936  augroup QF_Test
2937    au!
2938  augroup END
2939  cclose
2940
2941  " Fails with argument.
2942  augroup QF_Test
2943    au!
2944    au FileType qf call assert_fails(':file foo', 'E788')
2945  augroup END
2946  copen
2947  augroup QF_Test
2948    au!
2949  augroup END
2950  cclose
2951
2952  augroup! QF_Test
2953endfunc
2954
2955func Test_resize_from_copen()
2956    augroup QF_Test
2957	au!
2958        au FileType qf resize 5
2959    augroup END
2960    try
2961	" This should succeed without any exception.  No other buffers are
2962	" involved in the autocmd.
2963	copen
2964    finally
2965	augroup QF_Test
2966	    au!
2967	augroup END
2968	augroup! QF_Test
2969    endtry
2970endfunc
2971
2972" Tests for the quickfix buffer b:changedtick variable
2973func Xchangedtick_tests(cchar)
2974  call s:setup_commands(a:cchar)
2975
2976  new | only
2977
2978  Xexpr "" | Xexpr "" | Xexpr ""
2979
2980  Xopen
2981  Xolder
2982  Xolder
2983  Xaddexpr "F1:10:Line10"
2984  Xaddexpr "F2:20:Line20"
2985  call g:Xsetlist([{"filename":"F3", "lnum":30, "text":"Line30"}], 'a')
2986  call g:Xsetlist([], 'f')
2987  call assert_equal(8, getbufvar('%', 'changedtick'))
2988  Xclose
2989endfunc
2990
2991func Test_changedtick()
2992  call Xchangedtick_tests('c')
2993  call Xchangedtick_tests('l')
2994endfunc
2995
2996" Tests for parsing an expression using setqflist()
2997func Xsetexpr_tests(cchar)
2998  call s:setup_commands(a:cchar)
2999
3000  let t = ["File1:10:Line10", "File1:20:Line20"]
3001  call g:Xsetlist([], ' ', {'lines' : t})
3002  call g:Xsetlist([], 'a', {'lines' : ["File1:30:Line30"]})
3003
3004  let l = g:Xgetlist()
3005  call assert_equal(3, len(l))
3006  call assert_equal(20, l[1].lnum)
3007  call assert_equal('Line30', l[2].text)
3008  call g:Xsetlist([], 'r', {'lines' : ["File2:5:Line5"]})
3009  let l = g:Xgetlist()
3010  call assert_equal(1, len(l))
3011  call assert_equal('Line5', l[0].text)
3012  call assert_equal(-1, g:Xsetlist([], 'a', {'lines' : 10}))
3013  call assert_equal(-1, g:Xsetlist([], 'a', {'lines' : "F1:10:L10"}))
3014
3015  call g:Xsetlist([], 'f')
3016  " Add entries to multiple lists
3017  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["File1:10:Line10"]})
3018  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["File2:20:Line20"]})
3019  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["File1:15:Line15"]})
3020  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["File2:25:Line25"]})
3021  call assert_equal('Line15', g:Xgetlist({'nr':1, 'items':1}).items[1].text)
3022  call assert_equal('Line25', g:Xgetlist({'nr':2, 'items':1}).items[1].text)
3023
3024  " Adding entries using a custom efm
3025  set efm&
3026  call g:Xsetlist([], ' ', {'efm' : '%f#%l#%m',
3027				\ 'lines' : ["F1#10#L10", "F2#20#L20"]})
3028  call assert_equal(20, g:Xgetlist({'items':1}).items[1].lnum)
3029  call g:Xsetlist([], 'a', {'efm' : '%f#%l#%m', 'lines' : ["F3:30:L30"]})
3030  call assert_equal('F3:30:L30', g:Xgetlist({'items':1}).items[2].text)
3031  call assert_equal(20, g:Xgetlist({'items':1}).items[1].lnum)
3032  call assert_equal(-1, g:Xsetlist([], 'a', {'efm' : [],
3033				\ 'lines' : ['F1:10:L10']}))
3034endfunc
3035
3036func Test_setexpr()
3037  call Xsetexpr_tests('c')
3038  call Xsetexpr_tests('l')
3039endfunc
3040
3041" Tests for per quickfix/location list directory stack
3042func Xmultidirstack_tests(cchar)
3043  call s:setup_commands(a:cchar)
3044
3045  call g:Xsetlist([], 'f')
3046  Xexpr "" | Xexpr ""
3047
3048  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["Entering dir 'Xone/a'"]})
3049  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["Entering dir 'Xtwo/a'"]})
3050  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["one.txt:3:one one one"]})
3051  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["two.txt:5:two two two"]})
3052
3053  let l1 = g:Xgetlist({'nr':1, 'items':1})
3054  let l2 = g:Xgetlist({'nr':2, 'items':1})
3055  call assert_equal('Xone/a/one.txt', bufname(l1.items[1].bufnr))
3056  call assert_equal(3, l1.items[1].lnum)
3057  call assert_equal('Xtwo/a/two.txt', bufname(l2.items[1].bufnr))
3058  call assert_equal(5, l2.items[1].lnum)
3059endfunc
3060
3061func Test_multidirstack()
3062  call mkdir('Xone/a', 'p')
3063  call mkdir('Xtwo/a', 'p')
3064  let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7']
3065  call writefile(lines, 'Xone/a/one.txt')
3066  call writefile(lines, 'Xtwo/a/two.txt')
3067  let save_efm = &efm
3068  set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f'
3069
3070  call Xmultidirstack_tests('c')
3071  call Xmultidirstack_tests('l')
3072
3073  let &efm = save_efm
3074  call delete('Xone', 'rf')
3075  call delete('Xtwo', 'rf')
3076endfunc
3077
3078" Tests for per quickfix/location list file stack
3079func Xmultifilestack_tests(cchar)
3080  call s:setup_commands(a:cchar)
3081
3082  call g:Xsetlist([], 'f')
3083  Xexpr "" | Xexpr ""
3084
3085  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["[one.txt]"]})
3086  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["[two.txt]"]})
3087  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["(3,5) one one one"]})
3088  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["(5,9) two two two"]})
3089
3090  let l1 = g:Xgetlist({'nr':1, 'items':1})
3091  let l2 = g:Xgetlist({'nr':2, 'items':1})
3092  call assert_equal('one.txt', bufname(l1.items[1].bufnr))
3093  call assert_equal(3, l1.items[1].lnum)
3094  call assert_equal('two.txt', bufname(l2.items[1].bufnr))
3095  call assert_equal(5, l2.items[1].lnum)
3096
3097  " Test for start of a new error line in the same line where a previous
3098  " error line ends with a file stack.
3099  let efm_val = 'Error\ l%l\ in\ %f,'
3100  let efm_val .= '%-P%>(%f%r,Error\ l%l\ in\ %m,%-Q)%r'
3101  let l = g:Xgetlist({'lines' : [
3102	      \ '(one.txt',
3103	      \ 'Error l4 in one.txt',
3104	      \ ') (two.txt',
3105	      \ 'Error l6 in two.txt',
3106	      \ ')',
3107	      \ 'Error l8 in one.txt'
3108	      \ ], 'efm' : efm_val})
3109  call assert_equal(3, len(l.items))
3110  call assert_equal('one.txt', bufname(l.items[0].bufnr))
3111  call assert_equal(4, l.items[0].lnum)
3112  call assert_equal('one.txt', l.items[0].text)
3113  call assert_equal('two.txt', bufname(l.items[1].bufnr))
3114  call assert_equal(6, l.items[1].lnum)
3115  call assert_equal('two.txt', l.items[1].text)
3116  call assert_equal('one.txt', bufname(l.items[2].bufnr))
3117  call assert_equal(8, l.items[2].lnum)
3118  call assert_equal('', l.items[2].text)
3119endfunc
3120
3121func Test_multifilestack()
3122  let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7']
3123  call writefile(lines, 'one.txt')
3124  call writefile(lines, 'two.txt')
3125  let save_efm = &efm
3126  set efm=%+P[%f],(%l\\,%c)\ %m,%-Q
3127
3128  call Xmultifilestack_tests('c')
3129  call Xmultifilestack_tests('l')
3130
3131  let &efm = save_efm
3132  call delete('one.txt')
3133  call delete('two.txt')
3134endfunc
3135
3136" Tests for per buffer 'efm' setting
3137func Test_perbuf_efm()
3138  call writefile(["File1-10-Line10"], 'one.txt')
3139  call writefile(["File2#20#Line20"], 'two.txt')
3140  set efm=%f#%l#%m
3141  new | only
3142  new
3143  setlocal efm=%f-%l-%m
3144  cfile one.txt
3145  wincmd w
3146  caddfile two.txt
3147
3148  let l = getqflist()
3149  call assert_equal(10, l[0].lnum)
3150  call assert_equal('Line20', l[1].text)
3151
3152  set efm&
3153  new | only
3154  call delete('one.txt')
3155  call delete('two.txt')
3156endfunc
3157
3158" Open multiple help windows using ":lhelpgrep
3159" This test used to crash Vim
3160func Test_Multi_LL_Help()
3161    new | only
3162    lhelpgrep window
3163    lopen
3164    e#
3165    lhelpgrep buffer
3166    call assert_equal(3, winnr('$'))
3167    call assert_true(len(getloclist(1)) != 0)
3168    call assert_true(len(getloclist(2)) != 0)
3169    new | only
3170endfunc
3171
3172" Tests for adding new quickfix lists using setqflist()
3173func XaddQf_tests(cchar)
3174  call s:setup_commands(a:cchar)
3175
3176  " Create a new list using ' ' for action
3177  call g:Xsetlist([], 'f')
3178  call g:Xsetlist([], ' ', {'title' : 'Test1'})
3179  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3180  call assert_equal(1, l.nr)
3181  call assert_equal('Test1', l.title)
3182
3183  " Create a new list using ' ' for action and '$' for 'nr'
3184  call g:Xsetlist([], 'f')
3185  call g:Xsetlist([], ' ', {'title' : 'Test2', 'nr' : '$'})
3186  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3187  call assert_equal(1, l.nr)
3188  call assert_equal('Test2', l.title)
3189
3190  " Create a new list using 'a' for action
3191  call g:Xsetlist([], 'f')
3192  call g:Xsetlist([], 'a', {'title' : 'Test3'})
3193  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3194  call assert_equal(1, l.nr)
3195  call assert_equal('Test3', l.title)
3196
3197  " Create a new list using 'a' for action and '$' for 'nr'
3198  call g:Xsetlist([], 'f')
3199  call g:Xsetlist([], 'a', {'title' : 'Test3', 'nr' : '$'})
3200  call g:Xsetlist([], 'a', {'title' : 'Test4'})
3201  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3202  call assert_equal(1, l.nr)
3203  call assert_equal('Test4', l.title)
3204
3205  " Adding a quickfix list should remove all the lists following the current
3206  " list.
3207  Xexpr "" | Xexpr "" | Xexpr ""
3208  silent! 10Xolder
3209  call g:Xsetlist([], ' ', {'title' : 'Test5'})
3210  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3211  call assert_equal(2, l.nr)
3212  call assert_equal('Test5', l.title)
3213
3214  " Add a quickfix list using '$' as the list number.
3215  let lastqf = g:Xgetlist({'nr':'$'}).nr
3216  silent! 99Xolder
3217  call g:Xsetlist([], ' ', {'nr' : '$', 'title' : 'Test6'})
3218  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3219  call assert_equal(lastqf + 1, l.nr)
3220  call assert_equal('Test6', l.title)
3221
3222  " Add a quickfix list using 'nr' set to one more than the quickfix
3223  " list size.
3224  let lastqf = g:Xgetlist({'nr':'$'}).nr
3225  silent! 99Xolder
3226  call g:Xsetlist([], ' ', {'nr' : lastqf + 1, 'title' : 'Test7'})
3227  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3228  call assert_equal(lastqf + 1, l.nr)
3229  call assert_equal('Test7', l.title)
3230
3231  " Add a quickfix list to a stack with 10 lists using 'nr' set to '$'
3232  exe repeat('Xexpr "" |', 9) . 'Xexpr ""'
3233  silent! 99Xolder
3234  call g:Xsetlist([], ' ', {'nr' : '$', 'title' : 'Test8'})
3235  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3236  call assert_equal(10, l.nr)
3237  call assert_equal('Test8', l.title)
3238
3239  " Add a quickfix list using 'nr' set to a value greater than 10
3240  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : 12, 'title' : 'Test9'}))
3241
3242  " Try adding a quickfix list with 'nr' set to a value greater than the
3243  " quickfix list size but less than 10.
3244  call g:Xsetlist([], 'f')
3245  Xexpr "" | Xexpr "" | Xexpr ""
3246  silent! 99Xolder
3247  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : 8, 'title' : 'Test10'}))
3248
3249  " Add a quickfix list using 'nr' set to a some string or list
3250  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : [1,2], 'title' : 'Test11'}))
3251endfunc
3252
3253func Test_add_qf()
3254  call XaddQf_tests('c')
3255  call XaddQf_tests('l')
3256endfunc
3257
3258" Test for getting the quickfix list items from some text without modifying
3259" the quickfix stack
3260func XgetListFromLines(cchar)
3261  call s:setup_commands(a:cchar)
3262  call g:Xsetlist([], 'f')
3263
3264  let l = g:Xgetlist({'lines' : ["File2:20:Line20", "File2:30:Line30"]}).items
3265  call assert_equal(2, len(l))
3266  call assert_equal(30, l[1].lnum)
3267
3268  call assert_equal({}, g:Xgetlist({'lines' : 10}))
3269  call assert_equal({}, g:Xgetlist({'lines' : 'File1:10:Line10'}))
3270  call assert_equal([], g:Xgetlist({'lines' : []}).items)
3271  call assert_equal([], g:Xgetlist({'lines' : [10, 20]}).items)
3272
3273  " Parse text using a custom efm
3274  set efm&
3275  let l = g:Xgetlist({'lines':['File3#30#Line30'], 'efm' : '%f#%l#%m'}).items
3276  call assert_equal('Line30', l[0].text)
3277  let l = g:Xgetlist({'lines':['File3:30:Line30'], 'efm' : '%f-%l-%m'}).items
3278  call assert_equal('File3:30:Line30', l[0].text)
3279  let l = g:Xgetlist({'lines':['File3:30:Line30'], 'efm' : [1,2]})
3280  call assert_equal({}, l)
3281  call assert_fails("call g:Xgetlist({'lines':['abc'], 'efm':'%2'})", 'E376:')
3282  call assert_fails("call g:Xgetlist({'lines':['abc'], 'efm':''})", 'E378:')
3283
3284  " Make sure that the quickfix stack is not modified
3285  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
3286endfunc
3287
3288func Test_get_list_from_lines()
3289  call XgetListFromLines('c')
3290  call XgetListFromLines('l')
3291endfunc
3292
3293" Tests for the quickfix list id
3294func Xqfid_tests(cchar)
3295  call s:setup_commands(a:cchar)
3296
3297  call g:Xsetlist([], 'f')
3298  call assert_equal(0, g:Xgetlist({'id':0}).id)
3299  Xexpr ''
3300  let start_id = g:Xgetlist({'id' : 0}).id
3301  Xexpr '' | Xexpr ''
3302  Xolder
3303  call assert_equal(start_id, g:Xgetlist({'id':0, 'nr':1}).id)
3304  call assert_equal(start_id + 1, g:Xgetlist({'id':0, 'nr':0}).id)
3305  call assert_equal(start_id + 2, g:Xgetlist({'id':0, 'nr':'$'}).id)
3306  call assert_equal(0, g:Xgetlist({'id':0, 'nr':99}).id)
3307  call assert_equal(2, g:Xgetlist({'id':start_id + 1, 'nr':0}).nr)
3308  call assert_equal(0, g:Xgetlist({'id':99, 'nr':0}).id)
3309  call assert_equal(0, g:Xgetlist({'id':"abc", 'nr':0}).id)
3310
3311  call g:Xsetlist([], 'a', {'id':start_id, 'context':[1,2]})
3312  call assert_equal([1,2], g:Xgetlist({'nr':1, 'context':1}).context)
3313  call g:Xsetlist([], 'a', {'id':start_id+1, 'lines':['F1:10:L10']})
3314  call assert_equal('L10', g:Xgetlist({'nr':2, 'items':1}).items[0].text)
3315  call assert_equal(-1, g:Xsetlist([], 'a', {'id':999, 'title':'Vim'}))
3316  call assert_equal(-1, g:Xsetlist([], 'a', {'id':'abc', 'title':'Vim'}))
3317
3318  let qfid = g:Xgetlist({'id':0, 'nr':0})
3319  call g:Xsetlist([], 'f')
3320  call assert_equal(0, g:Xgetlist({'id':qfid, 'nr':0}).id)
3321endfunc
3322
3323func Test_qf_id()
3324  call Xqfid_tests('c')
3325  call Xqfid_tests('l')
3326endfunc
3327
3328func Xqfjump_tests(cchar)
3329  call s:setup_commands(a:cchar)
3330
3331  call writefile(["Line1\tFoo", "Line2"], 'F1')
3332  call writefile(["Line1\tBar", "Line2"], 'F2')
3333  call writefile(["Line1\tBaz", "Line2"], 'F3')
3334
3335  call g:Xsetlist([], 'f')
3336
3337  " Tests for
3338  "   Jumping to a line using a pattern
3339  "   Jumping to a column greater than the last column in a line
3340  "   Jumping to a line greater than the last line in the file
3341  let l = []
3342  for i in range(1, 7)
3343    call add(l, {})
3344  endfor
3345  let l[0].filename='F1'
3346  let l[0].pattern='Line1'
3347  let l[1].filename='F2'
3348  let l[1].pattern='Line1'
3349  let l[2].filename='F3'
3350  let l[2].pattern='Line1'
3351  let l[3].filename='F3'
3352  let l[3].lnum=1
3353  let l[3].col=9
3354  let l[3].vcol=1
3355  let l[4].filename='F3'
3356  let l[4].lnum=99
3357  let l[5].filename='F3'
3358  let l[5].lnum=1
3359  let l[5].col=99
3360  let l[5].vcol=1
3361  let l[6].filename='F3'
3362  let l[6].pattern='abcxyz'
3363
3364  call g:Xsetlist([], ' ', {'items' : l})
3365  Xopen | only
3366  2Xnext
3367  call assert_equal(3, g:Xgetlist({'idx' : 0}).idx)
3368  call assert_equal('F3', bufname('%'))
3369  Xnext
3370  call assert_equal(7, col('.'))
3371  Xnext
3372  call assert_equal(2, line('.'))
3373  Xnext
3374  call assert_equal(9, col('.'))
3375  2
3376  Xnext
3377  call assert_equal(2, line('.'))
3378
3379  if a:cchar == 'l'
3380    " When jumping to a location list entry in the location list window and
3381    " no usable windows are available, then a new window should be opened.
3382    enew! | new | only
3383    call g:Xsetlist([], 'f')
3384    setlocal buftype=nofile
3385    new
3386    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']})
3387    Xopen
3388    let winid = win_getid()
3389    wincmd p
3390    close
3391    call win_gotoid(winid)
3392    Xnext
3393    call assert_equal(3, winnr('$'))
3394    call assert_equal(1, winnr())
3395    call assert_equal(2, line('.'))
3396
3397    " When jumping to an entry in the location list window and the window
3398    " associated with the location list is not present and a window containing
3399    " the file is already present, then that window should be used.
3400    close
3401    belowright new
3402    call g:Xsetlist([], 'f')
3403    edit F3
3404    call win_gotoid(winid)
3405    Xlast
3406    call assert_equal(3, winnr())
3407    call assert_equal(6, g:Xgetlist({'size' : 1}).size)
3408    call assert_equal(winid, g:Xgetlist({'winid' : 1}).winid)
3409  endif
3410
3411  " Cleanup
3412  enew!
3413  new | only
3414
3415  call delete('F1')
3416  call delete('F2')
3417  call delete('F3')
3418endfunc
3419
3420func Test_qfjump()
3421  call Xqfjump_tests('c')
3422  call Xqfjump_tests('l')
3423endfunc
3424
3425" Tests for the getqflist() and getloclist() functions when the list is not
3426" present or is empty
3427func Xgetlist_empty_tests(cchar)
3428  call s:setup_commands(a:cchar)
3429
3430  " Empty quickfix stack
3431  call g:Xsetlist([], 'f')
3432  call assert_equal('', g:Xgetlist({'context' : 0}).context)
3433  call assert_equal(0, g:Xgetlist({'id' : 0}).id)
3434  call assert_equal(0, g:Xgetlist({'idx' : 0}).idx)
3435  call assert_equal([], g:Xgetlist({'items' : 0}).items)
3436  call assert_equal(0, g:Xgetlist({'nr' : 0}).nr)
3437  call assert_equal(0, g:Xgetlist({'size' : 0}).size)
3438  call assert_equal('', g:Xgetlist({'title' : 0}).title)
3439  call assert_equal(0, g:Xgetlist({'winid' : 0}).winid)
3440  call assert_equal(0, g:Xgetlist({'changedtick' : 0}).changedtick)
3441  if a:cchar == 'c'
3442    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0,
3443		  \ 'items' : [], 'nr' : 0, 'size' : 0, 'qfbufnr' : 0,
3444		  \ 'title' : '', 'winid' : 0, 'changedtick': 0},
3445		  \ g:Xgetlist({'all' : 0}))
3446  else
3447    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0,
3448		\ 'items' : [], 'nr' : 0, 'size' : 0, 'title' : '',
3449		\ 'winid' : 0, 'changedtick': 0, 'filewinid' : 0,
3450		\ 'qfbufnr' : 0},
3451		\ g:Xgetlist({'all' : 0}))
3452  endif
3453
3454  " Quickfix window with empty stack
3455  silent! Xopen
3456  let qfwinid = (a:cchar == 'c') ? win_getid() : 0
3457  let qfbufnr = (a:cchar == 'c') ? bufnr('') : 0
3458  call assert_equal(qfwinid, g:Xgetlist({'winid' : 0}).winid)
3459  Xclose
3460
3461  " Empty quickfix list
3462  Xexpr ""
3463  call assert_equal('', g:Xgetlist({'context' : 0}).context)
3464  call assert_notequal(0, g:Xgetlist({'id' : 0}).id)
3465  call assert_equal(0, g:Xgetlist({'idx' : 0}).idx)
3466  call assert_equal([], g:Xgetlist({'items' : 0}).items)
3467  call assert_notequal(0, g:Xgetlist({'nr' : 0}).nr)
3468  call assert_equal(0, g:Xgetlist({'size' : 0}).size)
3469  call assert_notequal('', g:Xgetlist({'title' : 0}).title)
3470  call assert_equal(0, g:Xgetlist({'winid' : 0}).winid)
3471  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3472
3473  let qfid = g:Xgetlist({'id' : 0}).id
3474  call g:Xsetlist([], 'f')
3475
3476  " Non-existing quickfix identifier
3477  call assert_equal('', g:Xgetlist({'id' : qfid, 'context' : 0}).context)
3478  call assert_equal(0, g:Xgetlist({'id' : qfid}).id)
3479  call assert_equal(0, g:Xgetlist({'id' : qfid, 'idx' : 0}).idx)
3480  call assert_equal([], g:Xgetlist({'id' : qfid, 'items' : 0}).items)
3481  call assert_equal(0, g:Xgetlist({'id' : qfid, 'nr' : 0}).nr)
3482  call assert_equal(0, g:Xgetlist({'id' : qfid, 'size' : 0}).size)
3483  call assert_equal('', g:Xgetlist({'id' : qfid, 'title' : 0}).title)
3484  call assert_equal(0, g:Xgetlist({'id' : qfid, 'winid' : 0}).winid)
3485  call assert_equal(0, g:Xgetlist({'id' : qfid, 'changedtick' : 0}).changedtick)
3486  if a:cchar == 'c'
3487    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
3488		\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
3489		\ 'qfbufnr' : qfbufnr,
3490		\ 'changedtick' : 0}, g:Xgetlist({'id' : qfid, 'all' : 0}))
3491  else
3492    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
3493		\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
3494		\ 'changedtick' : 0, 'filewinid' : 0, 'qfbufnr' : 0},
3495		\ g:Xgetlist({'id' : qfid, 'all' : 0}))
3496  endif
3497
3498  " Non-existing quickfix list number
3499  call assert_equal('', g:Xgetlist({'nr' : 5, 'context' : 0}).context)
3500  call assert_equal(0, g:Xgetlist({'nr' : 5}).nr)
3501  call assert_equal(0, g:Xgetlist({'nr' : 5, 'idx' : 0}).idx)
3502  call assert_equal([], g:Xgetlist({'nr' : 5, 'items' : 0}).items)
3503  call assert_equal(0, g:Xgetlist({'nr' : 5, 'id' : 0}).id)
3504  call assert_equal(0, g:Xgetlist({'nr' : 5, 'size' : 0}).size)
3505  call assert_equal('', g:Xgetlist({'nr' : 5, 'title' : 0}).title)
3506  call assert_equal(0, g:Xgetlist({'nr' : 5, 'winid' : 0}).winid)
3507  call assert_equal(0, g:Xgetlist({'nr' : 5, 'changedtick' : 0}).changedtick)
3508  if a:cchar == 'c'
3509    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
3510		\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
3511		\ 'changedtick' : 0, 'qfbufnr' : qfbufnr},
3512		\ g:Xgetlist({'nr' : 5, 'all' : 0}))
3513  else
3514    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
3515		\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
3516		\ 'changedtick' : 0, 'filewinid' : 0, 'qfbufnr' : 0},
3517		\ g:Xgetlist({'nr' : 5, 'all' : 0}))
3518  endif
3519endfunc
3520
3521func Test_getqflist()
3522  call Xgetlist_empty_tests('c')
3523  call Xgetlist_empty_tests('l')
3524endfunc
3525
3526func Test_getqflist_invalid_nr()
3527  " The following commands used to crash Vim
3528  cexpr ""
3529  call getqflist({'nr' : $XXX_DOES_NOT_EXIST_XXX})
3530
3531  " Cleanup
3532  call setqflist([], 'r')
3533endfunc
3534
3535" Tests for the quickfix/location list changedtick
3536func Xqftick_tests(cchar)
3537  call s:setup_commands(a:cchar)
3538
3539  call g:Xsetlist([], 'f')
3540
3541  Xexpr "F1:10:Line10"
3542  let qfid = g:Xgetlist({'id' : 0}).id
3543  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3544  Xaddexpr "F2:20:Line20\nF2:21:Line21"
3545  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
3546  call g:Xsetlist([], 'a', {'lines' : ["F3:30:Line30", "F3:31:Line31"]})
3547  call assert_equal(3, g:Xgetlist({'changedtick' : 0}).changedtick)
3548  call g:Xsetlist([], 'r', {'lines' : ["F4:40:Line40"]})
3549  call assert_equal(4, g:Xgetlist({'changedtick' : 0}).changedtick)
3550  call g:Xsetlist([], 'a', {'title' : 'New Title'})
3551  call assert_equal(5, g:Xgetlist({'changedtick' : 0}).changedtick)
3552
3553  enew!
3554  call append(0, ["F5:50:L50", "F6:60:L60"])
3555  Xaddbuffer
3556  call assert_equal(6, g:Xgetlist({'changedtick' : 0}).changedtick)
3557  enew!
3558
3559  call g:Xsetlist([], 'a', {'context' : {'bus' : 'pci'}})
3560  call assert_equal(7, g:Xgetlist({'changedtick' : 0}).changedtick)
3561  call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'},
3562	      \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], 'a')
3563  call assert_equal(8, g:Xgetlist({'changedtick' : 0}).changedtick)
3564  call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'},
3565	      \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], ' ')
3566  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3567  call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'},
3568	      \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], 'r')
3569  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
3570
3571  call writefile(["F8:80:L80", "F8:81:L81"], "Xone")
3572  Xfile Xone
3573  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3574  Xaddfile Xone
3575  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
3576
3577  " Test case for updating a non-current quickfix list
3578  call g:Xsetlist([], 'f')
3579  Xexpr "F1:1:L1"
3580  Xexpr "F2:2:L2"
3581  call g:Xsetlist([], 'a', {'nr' : 1, "lines" : ["F10:10:L10"]})
3582  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3583  call assert_equal(2, g:Xgetlist({'nr' : 1, 'changedtick' : 0}).changedtick)
3584
3585  call delete("Xone")
3586endfunc
3587
3588func Test_qf_tick()
3589  call Xqftick_tests('c')
3590  call Xqftick_tests('l')
3591endfunc
3592
3593" Test helpgrep with lang specifier
3594func Xtest_helpgrep_with_lang_specifier(cchar)
3595  call s:setup_commands(a:cchar)
3596  Xhelpgrep Vim@en
3597  call assert_equal('help', &filetype)
3598  call assert_notequal(0, g:Xgetlist({'nr' : '$'}).nr)
3599  new | only
3600endfunc
3601
3602func Test_helpgrep_with_lang_specifier()
3603  call Xtest_helpgrep_with_lang_specifier('c')
3604  call Xtest_helpgrep_with_lang_specifier('l')
3605endfunc
3606
3607" The following test used to crash Vim.
3608" Open the location list window and close the regular window associated with
3609" the location list. When the garbage collection runs now, it incorrectly
3610" marks the location list context as not in use and frees the context.
3611func Test_ll_window_ctx()
3612  call setloclist(0, [], 'f')
3613  call setloclist(0, [], 'a', {'context' : []})
3614  lopen | only
3615  call test_garbagecollect_now()
3616  echo getloclist(0, {'context' : 1}).context
3617  enew | only
3618endfunc
3619
3620" The following test used to crash vim
3621func Test_lfile_crash()
3622  sp Xtest
3623  au QuickFixCmdPre * bw
3624  call assert_fails('lfile', 'E40')
3625  au! QuickFixCmdPre
3626endfunc
3627
3628" The following test used to crash vim
3629func Test_lbuffer_crash()
3630  sv Xtest
3631  augroup QF_Test
3632    au!
3633    au * * bw
3634  augroup END
3635  lbuffer
3636  augroup QF_Test
3637    au!
3638  augroup END
3639endfunc
3640
3641" The following test used to crash vim
3642func Test_lexpr_crash()
3643  augroup QF_Test
3644    au!
3645    au * * call setloclist(0, [], 'f')
3646  augroup END
3647  lexpr ""
3648  augroup QF_Test
3649    au!
3650  augroup END
3651
3652  enew | only
3653  augroup QF_Test
3654    au!
3655    au BufNew * call setloclist(0, [], 'f')
3656  augroup END
3657  lexpr 'x:1:x'
3658  augroup QF_Test
3659    au!
3660  augroup END
3661
3662  enew | only
3663  lexpr ''
3664  lopen
3665  augroup QF_Test
3666    au!
3667    au FileType * call setloclist(0, [], 'f')
3668  augroup END
3669  lexpr ''
3670  augroup QF_Test
3671    au!
3672  augroup END
3673endfunc
3674
3675" The following test used to crash Vim
3676func Test_lvimgrep_crash()
3677  sv Xtest
3678  augroup QF_Test
3679    au!
3680    au * * call setloclist(0, [], 'f')
3681  augroup END
3682  lvimgrep quickfix test_quickfix.vim
3683  augroup QF_Test
3684    au!
3685  augroup END
3686
3687  new | only
3688  augroup QF_Test
3689    au!
3690    au BufEnter * call setloclist(0, [], 'r')
3691  augroup END
3692  call assert_fails('lvimgrep Test_lvimgrep_crash *', 'E926:')
3693  augroup QF_Test
3694    au!
3695  augroup END
3696
3697  enew | only
3698endfunc
3699
3700func Test_lvimgrep_crash2()
3701  au BufNewFile x sfind
3702  call assert_fails('lvimgrep x x', 'E480:')
3703  call assert_fails('lvimgrep x x x', 'E480:')
3704
3705  au! BufNewFile
3706endfunc
3707
3708" Test for the position of the quickfix and location list window
3709func Test_qfwin_pos()
3710  " Open two windows
3711  new | only
3712  new
3713  cexpr ['F1:10:L10']
3714  copen
3715  " Quickfix window should be the bottom most window
3716  call assert_equal(3, winnr())
3717  close
3718  " Open at the very top
3719  wincmd t
3720  topleft copen
3721  call assert_equal(1, winnr())
3722  close
3723  " open left of the current window
3724  wincmd t
3725  below new
3726  leftabove copen
3727  call assert_equal(2, winnr())
3728  close
3729  " open right of the current window
3730  rightbelow copen
3731  call assert_equal(3, winnr())
3732  close
3733endfunc
3734
3735" Tests for quickfix/location lists changed by autocommands when
3736" :vimgrep/:lvimgrep commands are running.
3737func Test_vimgrep_autocmd()
3738  call setqflist([], 'f')
3739  call writefile(['stars'], 'Xtest1.txt')
3740  call writefile(['stars'], 'Xtest2.txt')
3741
3742  " Test 1:
3743  " When searching for a pattern using :vimgrep, if the quickfix list is
3744  " changed by an autocmd, the results should be added to the correct quickfix
3745  " list.
3746  autocmd BufRead Xtest2.txt cexpr '' | cexpr ''
3747  silent vimgrep stars Xtest*.txt
3748  call assert_equal(1, getqflist({'nr' : 0}).nr)
3749  call assert_equal(3, getqflist({'nr' : '$'}).nr)
3750  call assert_equal('Xtest2.txt', bufname(getqflist()[1].bufnr))
3751  au! BufRead Xtest2.txt
3752
3753  " Test 2:
3754  " When searching for a pattern using :vimgrep, if the quickfix list is
3755  " freed, then a error should be given.
3756  silent! %bwipe!
3757  call setqflist([], 'f')
3758  autocmd BufRead Xtest2.txt for i in range(10) | cexpr '' | endfor
3759  call assert_fails('vimgrep stars Xtest*.txt', 'E925:')
3760  au! BufRead Xtest2.txt
3761
3762  " Test 3:
3763  " When searching for a pattern using :lvimgrep, if the location list is
3764  " freed, then the command should error out.
3765  silent! %bwipe!
3766  let g:save_winid = win_getid()
3767  autocmd BufRead Xtest2.txt call setloclist(g:save_winid, [], 'f')
3768  call assert_fails('lvimgrep stars Xtest*.txt', 'E926:')
3769  au! BufRead Xtest2.txt
3770
3771  call delete('Xtest1.txt')
3772  call delete('Xtest2.txt')
3773  call setqflist([], 'f')
3774endfunc
3775
3776" Test for an autocmd changing the current directory when running vimgrep
3777func Xvimgrep_autocmd_cd(cchar)
3778  call s:setup_commands(a:cchar)
3779
3780  %bwipe
3781  let save_cwd = getcwd()
3782
3783  augroup QF_Test
3784    au!
3785    autocmd BufRead * silent cd %:p:h
3786  augroup END
3787
3788  10Xvimgrep /vim/ Xdir/**
3789  let l = g:Xgetlist()
3790  call assert_equal('f1.txt', bufname(l[0].bufnr))
3791  call assert_equal('f2.txt', fnamemodify(bufname(l[2].bufnr), ':t'))
3792
3793  augroup QF_Test
3794    au!
3795  augroup END
3796
3797  exe 'cd ' . save_cwd
3798endfunc
3799
3800func Test_vimgrep_autocmd_cd()
3801  call mkdir('Xdir/a', 'p')
3802  call mkdir('Xdir/b', 'p')
3803  call writefile(['a_L1_vim', 'a_L2_vim'], 'Xdir/a/f1.txt')
3804  call writefile(['b_L1_vim', 'b_L2_vim'], 'Xdir/b/f2.txt')
3805  call Xvimgrep_autocmd_cd('c')
3806  call Xvimgrep_autocmd_cd('l')
3807  %bwipe
3808  call delete('Xdir', 'rf')
3809endfunc
3810
3811" The following test used to crash Vim
3812func Test_lhelpgrep_autocmd()
3813  lhelpgrep quickfix
3814  autocmd QuickFixCmdPost * call setloclist(0, [], 'f')
3815  lhelpgrep buffer
3816  call assert_equal('help', &filetype)
3817  call assert_equal(0, getloclist(0, {'nr' : '$'}).nr)
3818  lhelpgrep tabpage
3819  call assert_equal('help', &filetype)
3820  call assert_equal(1, getloclist(0, {'nr' : '$'}).nr)
3821  au! QuickFixCmdPost
3822
3823  new | only
3824  augroup QF_Test
3825    au!
3826    au BufEnter * call setqflist([], 'f')
3827  augroup END
3828  call assert_fails('helpgrep quickfix', 'E925:')
3829  augroup QF_Test
3830    au! BufEnter
3831  augroup END
3832
3833  new | only
3834  augroup QF_Test
3835    au!
3836    au BufEnter * call setqflist([], 'r')
3837  augroup END
3838  call assert_fails('helpgrep quickfix', 'E925:')
3839  augroup QF_Test
3840    au! BufEnter
3841  augroup END
3842
3843  new | only
3844  augroup QF_Test
3845    au!
3846    au BufEnter * call setloclist(0, [], 'r')
3847  augroup END
3848  call assert_fails('lhelpgrep quickfix', 'E926:')
3849  augroup QF_Test
3850    au! BufEnter
3851  augroup END
3852
3853  new | only
3854endfunc
3855
3856" Test for shortening/simplifying the file name when opening the
3857" quickfix window or when displaying the quickfix list
3858func Test_shorten_fname()
3859  if !has('unix')
3860    return
3861  endif
3862  %bwipe
3863  " Create a quickfix list with a absolute path filename
3864  let fname = getcwd() . '/test_quickfix.vim'
3865  call setqflist([], ' ', {'lines':[fname . ":20:Line20"], 'efm':'%f:%l:%m'})
3866  call assert_equal(fname, bufname('test_quickfix.vim'))
3867  " Opening the quickfix window should simplify the file path
3868  cwindow
3869  call assert_equal('test_quickfix.vim', bufname('test_quickfix.vim'))
3870  cclose
3871  %bwipe
3872  " Create a quickfix list with a absolute path filename
3873  call setqflist([], ' ', {'lines':[fname . ":20:Line20"], 'efm':'%f:%l:%m'})
3874  call assert_equal(fname, bufname('test_quickfix.vim'))
3875  " Displaying the quickfix list should simplify the file path
3876  silent! clist
3877  call assert_equal('test_quickfix.vim', bufname('test_quickfix.vim'))
3878endfunc
3879
3880" Quickfix title tests
3881" In the below tests, 'exe "cmd"' is used to invoke the quickfix commands.
3882" Otherwise due to indentation, the title is set with spaces at the beginning
3883" of the command.
3884func Test_qftitle()
3885  call writefile(["F1:1:Line1"], 'Xerr')
3886
3887  " :cexpr
3888  exe "cexpr readfile('Xerr')"
3889  call assert_equal(":cexpr readfile('Xerr')", getqflist({'title' : 1}).title)
3890
3891  " :cgetexpr
3892  exe "cgetexpr readfile('Xerr')"
3893  call assert_equal(":cgetexpr readfile('Xerr')",
3894					\ getqflist({'title' : 1}).title)
3895
3896  " :caddexpr
3897  call setqflist([], 'f')
3898  exe "caddexpr readfile('Xerr')"
3899  call assert_equal(":caddexpr readfile('Xerr')",
3900					\ getqflist({'title' : 1}).title)
3901
3902  " :cbuffer
3903  new Xerr
3904  exe "cbuffer"
3905  call assert_equal(':cbuffer (Xerr)', getqflist({'title' : 1}).title)
3906
3907  " :cgetbuffer
3908  edit Xerr
3909  exe "cgetbuffer"
3910  call assert_equal(':cgetbuffer (Xerr)', getqflist({'title' : 1}).title)
3911
3912  " :caddbuffer
3913  call setqflist([], 'f')
3914  edit Xerr
3915  exe "caddbuffer"
3916  call assert_equal(':caddbuffer (Xerr)', getqflist({'title' : 1}).title)
3917
3918  " :cfile
3919  exe "cfile Xerr"
3920  call assert_equal(':cfile Xerr', getqflist({'title' : 1}).title)
3921
3922  " :cgetfile
3923  exe "cgetfile Xerr"
3924  call assert_equal(':cgetfile Xerr', getqflist({'title' : 1}).title)
3925
3926  " :caddfile
3927  call setqflist([], 'f')
3928  exe "caddfile Xerr"
3929  call assert_equal(':caddfile Xerr', getqflist({'title' : 1}).title)
3930
3931  " :grep
3932  set grepprg=internal
3933  exe "grep F1 Xerr"
3934  call assert_equal(':grep F1 Xerr', getqflist({'title' : 1}).title)
3935
3936  " :grepadd
3937  call setqflist([], 'f')
3938  exe "grepadd F1 Xerr"
3939  call assert_equal(':grepadd F1 Xerr', getqflist({'title' : 1}).title)
3940  set grepprg&vim
3941
3942  " :vimgrep
3943  exe "vimgrep F1 Xerr"
3944  call assert_equal(':vimgrep F1 Xerr', getqflist({'title' : 1}).title)
3945
3946  " :vimgrepadd
3947  call setqflist([], 'f')
3948  exe "vimgrepadd F1 Xerr"
3949  call assert_equal(':vimgrepadd F1 Xerr', getqflist({'title' : 1}).title)
3950
3951  call setqflist(['F1:10:L10'], ' ')
3952  call assert_equal(':setqflist()', getqflist({'title' : 1}).title)
3953
3954  call setqflist([], 'f')
3955  call setqflist(['F1:10:L10'], 'a')
3956  call assert_equal(':setqflist()', getqflist({'title' : 1}).title)
3957
3958  call setqflist([], 'f')
3959  call setqflist(['F1:10:L10'], 'r')
3960  call assert_equal(':setqflist()', getqflist({'title' : 1}).title)
3961
3962  close
3963  call delete('Xerr')
3964
3965  call setqflist([], ' ', {'title' : 'Errors'})
3966  copen
3967  call assert_equal('Errors', w:quickfix_title)
3968  call setqflist([], 'r', {'items' : [{'filename' : 'a.c', 'lnum' : 10}]})
3969  call assert_equal('Errors', w:quickfix_title)
3970  cclose
3971endfunc
3972
3973func Test_lbuffer_with_bwipe()
3974  new
3975  new
3976  augroup nasty
3977    au * * bwipe
3978  augroup END
3979  lbuffer
3980  augroup nasty
3981    au!
3982  augroup END
3983endfunc
3984
3985" Test for an autocmd freeing the quickfix/location list when cexpr/lexpr is
3986" running
3987func Xexpr_acmd_freelist(cchar)
3988  call s:setup_commands(a:cchar)
3989
3990  " This was using freed memory.
3991  augroup nasty
3992    au * * call g:Xsetlist([], 'f')
3993  augroup END
3994  Xexpr "x"
3995  augroup nasty
3996    au!
3997  augroup END
3998endfunc
3999
4000func Test_cexpr_acmd_freelist()
4001  call Xexpr_acmd_freelist('c')
4002  call Xexpr_acmd_freelist('l')
4003endfunc
4004
4005" Test for commands that create a new quickfix/location list and jump to the
4006" first error automatically.
4007func Xjumpto_first_error_test(cchar)
4008  call s:setup_commands(a:cchar)
4009
4010  call s:create_test_file('Xtestfile1')
4011  call s:create_test_file('Xtestfile2')
4012  let l = ['Xtestfile1:2:Line2', 'Xtestfile2:4:Line4']
4013
4014  " Test for cexpr/lexpr
4015  enew
4016  Xexpr l
4017  call assert_equal('Xtestfile1', bufname(''))
4018  call assert_equal(2, line('.'))
4019
4020  " Test for cfile/lfile
4021  enew
4022  call writefile(l, 'Xerr')
4023  Xfile Xerr
4024  call assert_equal('Xtestfile1', bufname(''))
4025  call assert_equal(2, line('.'))
4026
4027  " Test for cbuffer/lbuffer
4028  edit Xerr
4029  Xbuffer
4030  call assert_equal('Xtestfile1', bufname(''))
4031  call assert_equal(2, line('.'))
4032
4033  call delete('Xerr')
4034  call delete('Xtestfile1')
4035  call delete('Xtestfile2')
4036endfunc
4037
4038func Test_jumpto_first_error()
4039  call Xjumpto_first_error_test('c')
4040  call Xjumpto_first_error_test('l')
4041endfunc
4042
4043" Test for a quickfix autocmd changing the quickfix/location list before
4044" jumping to the first error in the new list.
4045func Xautocmd_changelist(cchar)
4046  call s:setup_commands(a:cchar)
4047
4048  " Test for cfile/lfile
4049  call s:create_test_file('Xtestfile1')
4050  call s:create_test_file('Xtestfile2')
4051  Xexpr 'Xtestfile1:2:Line2'
4052  autocmd QuickFixCmdPost * Xolder
4053  call writefile(['Xtestfile2:4:Line4'], 'Xerr')
4054  Xfile Xerr
4055  call assert_equal('Xtestfile2', bufname(''))
4056  call assert_equal(4, line('.'))
4057  autocmd! QuickFixCmdPost
4058
4059  " Test for cbuffer/lbuffer
4060  call g:Xsetlist([], 'f')
4061  Xexpr 'Xtestfile1:2:Line2'
4062  autocmd QuickFixCmdPost * Xolder
4063  call writefile(['Xtestfile2:4:Line4'], 'Xerr')
4064  edit Xerr
4065  Xbuffer
4066  call assert_equal('Xtestfile2', bufname(''))
4067  call assert_equal(4, line('.'))
4068  autocmd! QuickFixCmdPost
4069
4070  " Test for cexpr/lexpr
4071  call g:Xsetlist([], 'f')
4072  Xexpr 'Xtestfile1:2:Line2'
4073  autocmd QuickFixCmdPost * Xolder
4074  Xexpr 'Xtestfile2:4:Line4'
4075  call assert_equal('Xtestfile2', bufname(''))
4076  call assert_equal(4, line('.'))
4077  autocmd! QuickFixCmdPost
4078
4079  " The grepprg may not be set on non-Unix systems
4080  if has('unix')
4081    " Test for grep/lgrep
4082    call g:Xsetlist([], 'f')
4083    Xexpr 'Xtestfile1:2:Line2'
4084    autocmd QuickFixCmdPost * Xolder
4085    silent Xgrep Line5 Xtestfile2
4086    call assert_equal('Xtestfile2', bufname(''))
4087    call assert_equal(5, line('.'))
4088    autocmd! QuickFixCmdPost
4089  endif
4090
4091  " Test for vimgrep/lvimgrep
4092  call g:Xsetlist([], 'f')
4093  Xexpr 'Xtestfile1:2:Line2'
4094  autocmd QuickFixCmdPost * Xolder
4095  silent Xvimgrep Line5 Xtestfile2
4096  call assert_equal('Xtestfile2', bufname(''))
4097  call assert_equal(5, line('.'))
4098  autocmd! QuickFixCmdPost
4099
4100  " Test for autocommands clearing the quickfix list before jumping to the
4101  " first error. This should not result in an error
4102  autocmd QuickFixCmdPost * call g:Xsetlist([], 'r')
4103  let v:errmsg = ''
4104  " Test for cfile/lfile
4105  Xfile Xerr
4106  call assert_true(v:errmsg !~# 'E42:')
4107  " Test for cbuffer/lbuffer
4108  edit Xerr
4109  Xbuffer
4110  call assert_true(v:errmsg !~# 'E42:')
4111  " Test for cexpr/lexpr
4112  Xexpr 'Xtestfile2:4:Line4'
4113  call assert_true(v:errmsg !~# 'E42:')
4114  " Test for grep/lgrep
4115  " The grepprg may not be set on non-Unix systems
4116  if has('unix')
4117    silent Xgrep Line5 Xtestfile2
4118    call assert_true(v:errmsg !~# 'E42:')
4119  endif
4120  " Test for vimgrep/lvimgrep
4121  call assert_fails('silent Xvimgrep Line5 Xtestfile2', 'E480:')
4122  autocmd! QuickFixCmdPost
4123
4124  call delete('Xerr')
4125  call delete('Xtestfile1')
4126  call delete('Xtestfile2')
4127endfunc
4128
4129func Test_autocmd_changelist()
4130  call Xautocmd_changelist('c')
4131  call Xautocmd_changelist('l')
4132endfunc
4133
4134" Tests for the ':filter /pat/ clist' command
4135func Test_filter_clist()
4136  cexpr ['Xfile1:10:10:Line 10', 'Xfile2:15:15:Line 15']
4137  call assert_equal([' 2 Xfile2:15 col 15: Line 15'],
4138			\ split(execute('filter /Line 15/ clist'), "\n"))
4139  call assert_equal([' 1 Xfile1:10 col 10: Line 10'],
4140			\ split(execute('filter /Xfile1/ clist'), "\n"))
4141  call assert_equal([], split(execute('filter /abc/ clist'), "\n"))
4142
4143  call setqflist([{'module' : 'abc', 'pattern' : 'pat1'},
4144			\ {'module' : 'pqr', 'pattern' : 'pat2'}], ' ')
4145  call assert_equal([' 2 pqr:pat2:  '],
4146			\ split(execute('filter /pqr/ clist'), "\n"))
4147  call assert_equal([' 1 abc:pat1:  '],
4148			\ split(execute('filter /pat1/ clist'), "\n"))
4149endfunc
4150
4151" Tests for the "CTRL-W <CR>" command.
4152func Xview_result_split_tests(cchar)
4153  call s:setup_commands(a:cchar)
4154
4155  " Test that "CTRL-W <CR>" in a qf/ll window fails with empty list.
4156  call g:Xsetlist([])
4157  Xopen
4158  let l:win_count = winnr('$')
4159  call assert_fails('execute "normal! \<C-W>\<CR>"', 'E42')
4160  call assert_equal(l:win_count, winnr('$'))
4161  Xclose
4162endfunc
4163
4164func Test_view_result_split()
4165  call Xview_result_split_tests('c')
4166  call Xview_result_split_tests('l')
4167endfunc
4168
4169" Test that :cc sets curswant
4170func Test_curswant()
4171  helpgrep quickfix
4172  normal! llll
4173  1cc
4174  call assert_equal(getcurpos()[4], virtcol('.'))
4175  cclose | helpclose
4176endfunc
4177
4178" Test for opening a file from the quickfix window using CTRL-W <Enter>
4179" doesn't leave an empty buffer around.
4180func Test_splitview()
4181  call s:create_test_file('Xtestfile1')
4182  call s:create_test_file('Xtestfile2')
4183  new | only
4184  let last_bufnr = bufnr('Test_sv_1', 1)
4185  let l = ['Xtestfile1:2:Line2', 'Xtestfile2:4:Line4']
4186  cgetexpr l
4187  copen
4188  let numbufs = len(getbufinfo())
4189  exe "normal \<C-W>\<CR>"
4190  copen
4191  exe "normal j\<C-W>\<CR>"
4192  " Make sure new empty buffers are not created
4193  call assert_equal(numbufs, len(getbufinfo()))
4194  " Creating a new buffer should use the next available buffer number
4195  call assert_equal(last_bufnr + 4, bufnr("Test_sv_2", 1))
4196  bwipe Test_sv_1
4197  bwipe Test_sv_2
4198  new | only
4199
4200  " When split opening files from location list window, make sure that two
4201  " windows doesn't refer to the same location list
4202  lgetexpr l
4203  let locid = getloclist(0, {'id' : 0}).id
4204  lopen
4205  exe "normal \<C-W>\<CR>"
4206  call assert_notequal(locid, getloclist(0, {'id' : 0}).id)
4207  call assert_equal(0, getloclist(0, {'winid' : 0}).winid)
4208  new | only
4209
4210  " When split opening files from a helpgrep location list window, a new help
4211  " window should be opened with a copy of the location list.
4212  lhelpgrep window
4213  let locid = getloclist(0, {'id' : 0}).id
4214  lwindow
4215  exe "normal j\<C-W>\<CR>"
4216  call assert_notequal(locid, getloclist(0, {'id' : 0}).id)
4217  call assert_equal(0, getloclist(0, {'winid' : 0}).winid)
4218  new | only
4219
4220  " Using :split or :vsplit from a quickfix window should behave like a :new
4221  " or a :vnew command
4222  copen
4223  split
4224  call assert_equal(3, winnr('$'))
4225  let l = getwininfo()
4226  call assert_equal([0, 0, 1], [l[0].quickfix, l[1].quickfix, l[2].quickfix])
4227  close
4228  copen
4229  vsplit
4230  let l = getwininfo()
4231  call assert_equal([0, 0, 1], [l[0].quickfix, l[1].quickfix, l[2].quickfix])
4232  new | only
4233
4234  call delete('Xtestfile1')
4235  call delete('Xtestfile2')
4236endfunc
4237
4238" Test for parsing entries using visual screen column
4239func Test_viscol()
4240  enew
4241  call writefile(["Col1\tCol2\tCol3"], 'Xfile1')
4242  edit Xfile1
4243
4244  " Use byte offset for column number
4245  set efm&
4246  cexpr "Xfile1:1:5:XX\nXfile1:1:9:YY\nXfile1:1:20:ZZ"
4247  call assert_equal([5, 8], [col('.'), virtcol('.')])
4248  cnext
4249  call assert_equal([9, 12], [col('.'), virtcol('.')])
4250  cnext
4251  call assert_equal([14, 20], [col('.'), virtcol('.')])
4252
4253  " Use screen column offset for column number
4254  set efm=%f:%l:%v:%m
4255  cexpr "Xfile1:1:8:XX\nXfile1:1:12:YY\nXfile1:1:20:ZZ"
4256  call assert_equal([5, 8], [col('.'), virtcol('.')])
4257  cnext
4258  call assert_equal([9, 12], [col('.'), virtcol('.')])
4259  cnext
4260  call assert_equal([14, 20], [col('.'), virtcol('.')])
4261  cexpr "Xfile1:1:6:XX\nXfile1:1:15:YY\nXfile1:1:24:ZZ"
4262  call assert_equal([5, 8], [col('.'), virtcol('.')])
4263  cnext
4264  call assert_equal([10, 16], [col('.'), virtcol('.')])
4265  cnext
4266  call assert_equal([14, 20], [col('.'), virtcol('.')])
4267
4268  enew
4269  call writefile(["Col1\täü\töß\tCol4"], 'Xfile1')
4270
4271  " Use byte offset for column number
4272  set efm&
4273  cexpr "Xfile1:1:8:XX\nXfile1:1:11:YY\nXfile1:1:16:ZZ"
4274  call assert_equal([8, 10], [col('.'), virtcol('.')])
4275  cnext
4276  call assert_equal([11, 17], [col('.'), virtcol('.')])
4277  cnext
4278  call assert_equal([16, 25], [col('.'), virtcol('.')])
4279
4280  " Use screen column offset for column number
4281  set efm=%f:%l:%v:%m
4282  cexpr "Xfile1:1:10:XX\nXfile1:1:17:YY\nXfile1:1:25:ZZ"
4283  call assert_equal([8, 10], [col('.'), virtcol('.')])
4284  cnext
4285  call assert_equal([11, 17], [col('.'), virtcol('.')])
4286  cnext
4287  call assert_equal([16, 25], [col('.'), virtcol('.')])
4288
4289  enew | only
4290  set efm&
4291  call delete('Xfile1')
4292endfunc
4293
4294" Test for the quickfix window buffer
4295func Xqfbuf_test(cchar)
4296  call s:setup_commands(a:cchar)
4297
4298  " Quickfix buffer should be reused across closing and opening a quickfix
4299  " window
4300  Xexpr "F1:10:Line10"
4301  Xopen
4302  let qfbnum = bufnr('')
4303  Xclose
4304  " Even after the quickfix window is closed, the buffer should be loaded
4305  call assert_true(bufloaded(qfbnum))
4306  call assert_true(qfbnum, g:Xgetlist({'qfbufnr' : 0}).qfbufnr)
4307  Xopen
4308  " Buffer should be reused when opening the window again
4309  call assert_equal(qfbnum, bufnr(''))
4310  Xclose
4311
4312  if a:cchar == 'l'
4313    %bwipe
4314    " For a location list, when both the file window and the location list
4315    " window for the list are closed, then the buffer should be freed.
4316    new | only
4317    lexpr "F1:10:Line10"
4318    let wid = win_getid()
4319    lopen
4320    let qfbnum = bufnr('')
4321    call assert_match(qfbnum . ' %a-  "\[Location List]"', execute('ls'))
4322    close
4323    " When the location list window is closed, the buffer name should not
4324    " change to 'Quickfix List'
4325    call assert_match(qfbnum . 'u h-  "\[Location List]"', execute('ls!'))
4326    call assert_true(bufloaded(qfbnum))
4327
4328    " After deleting a location list buffer using ":bdelete", opening the
4329    " location list window should mark the buffer as a location list buffer.
4330    exe "bdelete " . qfbnum
4331    lopen
4332    call assert_equal("quickfix", &buftype)
4333    call assert_equal(1, getwininfo(win_getid(winnr()))[0].loclist)
4334    call assert_equal(wid, getloclist(0, {'filewinid' : 0}).filewinid)
4335    call assert_false(&swapfile)
4336    lclose
4337
4338    " When the location list is cleared for the window, the buffer should be
4339    " removed
4340    call setloclist(0, [], 'f')
4341    call assert_false(bufexists(qfbnum))
4342    call assert_equal(0, getloclist(0, {'qfbufnr' : 0}).qfbufnr)
4343
4344    " When the location list is freed with the location list window open, the
4345    " location list buffer should not be lost. It should be reused when the
4346    " location list is again populated.
4347    lexpr "F1:10:Line10"
4348    lopen
4349    let wid = win_getid()
4350    let qfbnum = bufnr('')
4351    wincmd p
4352    call setloclist(0, [], 'f')
4353    lexpr "F1:10:Line10"
4354    lopen
4355    call assert_equal(wid, win_getid())
4356    call assert_equal(qfbnum, bufnr(''))
4357    lclose
4358
4359    " When the window with the location list is closed, the buffer should be
4360    " removed
4361    new | only
4362    call assert_false(bufexists(qfbnum))
4363  endif
4364endfunc
4365
4366func Test_qfbuf()
4367  call Xqfbuf_test('c')
4368  call Xqfbuf_test('l')
4369endfunc
4370
4371" If there is an autocmd to use only one window, then opening the location
4372" list window used to crash Vim.
4373func Test_winonly_autocmd()
4374  call s:create_test_file('Xtest1')
4375  " Autocmd to show only one Vim window at a time
4376  autocmd WinEnter * only
4377  new
4378  " Load the location list
4379  lexpr "Xtest1:5:Line5\nXtest1:10:Line10\nXtest1:15:Line15"
4380  let loclistid = getloclist(0, {'id' : 0}).id
4381  " Open the location list window. Only this window will be shown and the file
4382  " window is closed.
4383  lopen
4384  call assert_equal(loclistid, getloclist(0, {'id' : 0}).id)
4385  " Jump to an entry in the location list and make sure that the cursor is
4386  " positioned correctly.
4387  ll 3
4388  call assert_equal(loclistid, getloclist(0, {'id' : 0}).id)
4389  call assert_equal('Xtest1', bufname(''))
4390  call assert_equal(15, line('.'))
4391  " Cleanup
4392  autocmd! WinEnter
4393  new | only
4394  call delete('Xtest1')
4395endfunc
4396
4397" Test to make sure that an empty quickfix buffer is not reused for loading
4398" a normal buffer.
4399func Test_empty_qfbuf()
4400  enew | only
4401  call writefile(["Test"], 'Xfile1')
4402  call setqflist([], 'f')
4403  copen | only
4404  let qfbuf = bufnr('')
4405  edit Xfile1
4406  call assert_notequal(qfbuf, bufnr(''))
4407  enew
4408  call delete('Xfile1')
4409endfunc
4410
4411" Test for the :cbelow, :cabove, :lbelow and :labove commands.
4412" And for the :cafter, :cbefore, :lafter and :lbefore commands.
4413func Xtest_below(cchar)
4414  call s:setup_commands(a:cchar)
4415
4416  " No quickfix/location list
4417  call assert_fails('Xbelow', 'E42:')
4418  call assert_fails('Xabove', 'E42:')
4419  call assert_fails('Xbefore', 'E42:')
4420  call assert_fails('Xafter', 'E42:')
4421
4422  " Empty quickfix/location list
4423  call g:Xsetlist([])
4424  call assert_fails('Xbelow', 'E42:')
4425  call assert_fails('Xabove', 'E42:')
4426  call assert_fails('Xbefore', 'E42:')
4427  call assert_fails('Xafter', 'E42:')
4428
4429  call s:create_test_file('X1')
4430  call s:create_test_file('X2')
4431  call s:create_test_file('X3')
4432  call s:create_test_file('X4')
4433
4434  " Invalid entries
4435  edit X1
4436  call g:Xsetlist(["E1", "E2"])
4437  call assert_fails('Xbelow', 'E42:')
4438  call assert_fails('Xabove', 'E42:')
4439  call assert_fails('3Xbelow', 'E42:')
4440  call assert_fails('4Xabove', 'E42:')
4441  call assert_fails('Xbefore', 'E42:')
4442  call assert_fails('Xafter', 'E42:')
4443  call assert_fails('3Xbefore', 'E42:')
4444  call assert_fails('4Xafter', 'E42:')
4445
4446  " Test the commands with various arguments
4447  Xexpr ["X1:5:3:L5", "X2:5:2:L5", "X2:10:3:L10", "X2:15:4:L15", "X3:3:5:L3"]
4448  edit +7 X2
4449  Xabove
4450  call assert_equal(['X2', 5], [bufname(''), line('.')])
4451  call assert_fails('Xabove', 'E553:')
4452  normal 7G
4453  Xbefore
4454  call assert_equal(['X2', 5, 2], [bufname(''), line('.'), col('.')])
4455  call assert_fails('Xbefore', 'E553:')
4456
4457  normal 2j
4458  Xbelow
4459  call assert_equal(['X2', 10], [bufname(''), line('.')])
4460  normal 7G
4461  Xafter
4462  call assert_equal(['X2', 10, 3], [bufname(''), line('.'), col('.')])
4463
4464  " Last error in this file
4465  Xbelow 99
4466  call assert_equal(['X2', 15], [bufname(''), line('.')])
4467  call assert_fails('Xbelow', 'E553:')
4468  normal gg
4469  Xafter 99
4470  call assert_equal(['X2', 15, 4], [bufname(''), line('.'), col('.')])
4471  call assert_fails('Xafter', 'E553:')
4472
4473  " First error in this file
4474  Xabove 99
4475  call assert_equal(['X2', 5], [bufname(''), line('.')])
4476  call assert_fails('Xabove', 'E553:')
4477  normal G
4478  Xbefore 99
4479  call assert_equal(['X2', 5, 2], [bufname(''), line('.'), col('.')])
4480  call assert_fails('Xbefore', 'E553:')
4481
4482  normal gg
4483  Xbelow 2
4484  call assert_equal(['X2', 10], [bufname(''), line('.')])
4485  normal gg
4486  Xafter 2
4487  call assert_equal(['X2', 10, 3], [bufname(''), line('.'), col('.')])
4488
4489  normal G
4490  Xabove 2
4491  call assert_equal(['X2', 10], [bufname(''), line('.')])
4492  normal G
4493  Xbefore 2
4494  call assert_equal(['X2', 10, 3], [bufname(''), line('.'), col('.')])
4495
4496  edit X4
4497  call assert_fails('Xabove', 'E42:')
4498  call assert_fails('Xbelow', 'E42:')
4499  call assert_fails('Xbefore', 'E42:')
4500  call assert_fails('Xafter', 'E42:')
4501  if a:cchar == 'l'
4502    " If a buffer has location list entries from some other window but not
4503    " from the current window, then the commands should fail.
4504    edit X1 | split | call setloclist(0, [], 'f')
4505    call assert_fails('Xabove', 'E776:')
4506    call assert_fails('Xbelow', 'E776:')
4507    call assert_fails('Xbefore', 'E776:')
4508    call assert_fails('Xafter', 'E776:')
4509    close
4510  endif
4511
4512  " Test for lines with multiple quickfix entries
4513  Xexpr ["X1:5:L5", "X2:5:1:L5_1", "X2:5:2:L5_2", "X2:5:3:L5_3",
4514	      \ "X2:10:1:L10_1", "X2:10:2:L10_2", "X2:10:3:L10_3",
4515	      \ "X2:15:1:L15_1", "X2:15:2:L15_2", "X2:15:3:L15_3", "X3:3:L3"]
4516  edit +1 X2
4517  Xbelow 2
4518  call assert_equal(['X2', 10, 1], [bufname(''), line('.'), col('.')])
4519  normal 1G
4520  Xafter 2
4521  call assert_equal(['X2', 5, 2], [bufname(''), line('.'), col('.')])
4522
4523  normal gg
4524  Xbelow 99
4525  call assert_equal(['X2', 15, 1], [bufname(''), line('.'), col('.')])
4526  normal gg
4527  Xafter 99
4528  call assert_equal(['X2', 15, 3], [bufname(''), line('.'), col('.')])
4529
4530  normal G
4531  Xabove 2
4532  call assert_equal(['X2', 10, 1], [bufname(''), line('.'), col('.')])
4533  normal G
4534  Xbefore 2
4535  call assert_equal(['X2', 15, 2], [bufname(''), line('.'), col('.')])
4536
4537  normal G
4538  Xabove 99
4539  call assert_equal(['X2', 5, 1], [bufname(''), line('.'), col('.')])
4540  normal G
4541  Xbefore 99
4542  call assert_equal(['X2', 5, 1], [bufname(''), line('.'), col('.')])
4543
4544  normal 10G
4545  Xabove
4546  call assert_equal(['X2', 5, 1], [bufname(''), line('.'), col('.')])
4547  normal 10G$
4548  2Xbefore
4549  call assert_equal(['X2', 10, 2], [bufname(''), line('.'), col('.')])
4550
4551  normal 10G
4552  Xbelow
4553  call assert_equal(['X2', 15, 1], [bufname(''), line('.'), col('.')])
4554  normal 9G
4555  5Xafter
4556  call assert_equal(['X2', 15, 2], [bufname(''), line('.'), col('.')])
4557
4558  " Invalid range
4559  if a:cchar == 'c'
4560    call assert_fails('-2cbelow', 'E16:')
4561    call assert_fails('-2cafter', 'E16:')
4562  else
4563    call assert_fails('-2lbelow', 'E16:')
4564    call assert_fails('-2lafter', 'E16:')
4565  endif
4566
4567  call delete('X1')
4568  call delete('X2')
4569  call delete('X3')
4570  call delete('X4')
4571endfunc
4572
4573func Test_cbelow()
4574  call Xtest_below('c')
4575  call Xtest_below('l')
4576endfunc
4577
4578func Test_quickfix_count()
4579  let commands = [
4580	\ 'cNext',
4581	\ 'cNfile',
4582	\ 'cabove',
4583	\ 'cbelow',
4584	\ 'cfirst',
4585	\ 'clast',
4586	\ 'cnewer',
4587	\ 'cnext',
4588	\ 'cnfile',
4589	\ 'colder',
4590	\ 'cprevious',
4591	\ 'crewind',
4592	\
4593	\ 'lNext',
4594	\ 'lNfile',
4595	\ 'labove',
4596	\ 'lbelow',
4597	\ 'lfirst',
4598	\ 'llast',
4599	\ 'lnewer',
4600	\ 'lnext',
4601	\ 'lnfile',
4602	\ 'lolder',
4603	\ 'lprevious',
4604	\ 'lrewind',
4605	\ ]
4606  for cmd in commands
4607    call assert_fails('-1' .. cmd, 'E16:')
4608    call assert_fails('.' .. cmd, 'E16:')
4609    call assert_fails('%' .. cmd, 'E16:')
4610    call assert_fails('$' .. cmd, 'E16:')
4611  endfor
4612endfunc
4613
4614" Test for aborting quickfix commands using QuickFixCmdPre
4615func Xtest_qfcmd_abort(cchar)
4616  call s:setup_commands(a:cchar)
4617
4618  call g:Xsetlist([], 'f')
4619
4620  " cexpr/lexpr
4621  let e = ''
4622  try
4623    Xexpr ["F1:10:Line10", "F2:20:Line20"]
4624  catch /.*/
4625    let e = v:exception
4626  endtry
4627  call assert_equal('AbortCmd', e)
4628  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4629
4630  " cfile/lfile
4631  call writefile(["F1:10:Line10", "F2:20:Line20"], 'Xfile1')
4632  let e = ''
4633  try
4634    Xfile Xfile1
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  call delete('Xfile1')
4641
4642  " cgetbuffer/lgetbuffer
4643  enew!
4644  call append(0, ["F1:10:Line10", "F2:20:Line20"])
4645  let e = ''
4646  try
4647    Xgetbuffer
4648  catch /.*/
4649    let e = v:exception
4650  endtry
4651  call assert_equal('AbortCmd', e)
4652  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4653  enew!
4654
4655  " vimgrep/lvimgrep
4656  let e = ''
4657  try
4658    Xvimgrep /func/ test_quickfix.vim
4659  catch /.*/
4660    let e = v:exception
4661  endtry
4662  call assert_equal('AbortCmd', e)
4663  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4664
4665  " helpgrep/lhelpgrep
4666  let e = ''
4667  try
4668    Xhelpgrep quickfix
4669  catch /.*/
4670    let e = v:exception
4671  endtry
4672  call assert_equal('AbortCmd', e)
4673  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4674
4675  " grep/lgrep
4676  if has('unix')
4677    let e = ''
4678    try
4679      silent Xgrep func test_quickfix.vim
4680    catch /.*/
4681      let e = v:exception
4682    endtry
4683    call assert_equal('AbortCmd', e)
4684    call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4685  endif
4686endfunc
4687
4688func Test_qfcmd_abort()
4689  augroup QF_Test
4690    au!
4691    autocmd  QuickFixCmdPre * throw "AbortCmd"
4692  augroup END
4693
4694  call Xtest_qfcmd_abort('c')
4695  call Xtest_qfcmd_abort('l')
4696
4697  augroup QF_Test
4698    au!
4699  augroup END
4700endfunc
4701
4702" Test for using a file in one of the parent directories.
4703func Test_search_in_dirstack()
4704  call mkdir('Xtestdir/a/b/c', 'p')
4705  let save_cwd = getcwd()
4706  call writefile(["X1_L1", "X1_L2"], 'Xtestdir/Xfile1')
4707  call writefile(["X2_L1", "X2_L2"], 'Xtestdir/a/Xfile2')
4708  call writefile(["X3_L1", "X3_L2"], 'Xtestdir/a/b/Xfile3')
4709  call writefile(["X4_L1", "X4_L2"], 'Xtestdir/a/b/c/Xfile4')
4710
4711  let lines = "Entering dir Xtestdir\n" .
4712	      \ "Entering dir a\n" .
4713	      \ "Entering dir b\n" .
4714	      \ "Xfile2:2:X2_L2\n" .
4715	      \ "Leaving dir a\n" .
4716	      \ "Xfile1:2:X1_L2\n" .
4717	      \ "Xfile3:1:X3_L1\n" .
4718	      \ "Entering dir c\n" .
4719	      \ "Xfile4:2:X4_L2\n" .
4720	      \ "Leaving dir c\n"
4721  set efm=%DEntering\ dir\ %f,%XLeaving\ dir\ %f,%f:%l:%m
4722  cexpr lines .. "Leaving dir Xtestdir|\n" | let next = 1
4723  call assert_equal(11, getqflist({'size' : 0}).size)
4724  call assert_equal(4, getqflist({'idx' : 0}).idx)
4725  call assert_equal('X2_L2', getline('.'))
4726  call assert_equal(1, next)
4727  cnext
4728  call assert_equal(6, getqflist({'idx' : 0}).idx)
4729  call assert_equal('X1_L2', getline('.'))
4730  cnext
4731  call assert_equal(7, getqflist({'idx' : 0}).idx)
4732  call assert_equal(1, line('$'))
4733  call assert_equal('', getline(1))
4734  cnext
4735  call assert_equal(9, getqflist({'idx' : 0}).idx)
4736  call assert_equal(1, line('$'))
4737  call assert_equal('', getline(1))
4738
4739  set efm&
4740  exe 'cd ' . save_cwd
4741  call delete('Xtestdir', 'rf')
4742endfunc
4743
4744" Test for :cquit
4745func Test_cquit()
4746  " Exit Vim with a non-zero value
4747  if RunVim([], ["cquit 7"], '')
4748    call assert_equal(7, v:shell_error)
4749  endif
4750
4751  if RunVim([], ["50cquit"], '')
4752    call assert_equal(50, v:shell_error)
4753  endif
4754
4755  " Exit Vim with default value
4756  if RunVim([], ["cquit"], '')
4757    call assert_equal(1, v:shell_error)
4758  endif
4759
4760  " Exit Vim with zero value
4761  if RunVim([], ["cquit 0"], '')
4762    call assert_equal(0, v:shell_error)
4763  endif
4764
4765  " Exit Vim with negative value
4766  call assert_fails('-3cquit', 'E16:')
4767endfunc
4768
4769" vim: shiftwidth=2 sts=2 expandtab
4770