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