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