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