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