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  " run the test with a help window already open
3953  help
3954  wincmd w
3955  call assert_fails('helpgrep quickfix', 'E925:')
3956  augroup QF_Test
3957    au! BufEnter
3958  augroup END
3959
3960  new | only
3961  augroup QF_Test
3962    au!
3963    au BufEnter * call setqflist([], 'r')
3964  augroup END
3965  call assert_fails('helpgrep quickfix', 'E925:')
3966  augroup QF_Test
3967    au! BufEnter
3968  augroup END
3969
3970  new | only
3971  augroup QF_Test
3972    au!
3973    au BufEnter * call setloclist(0, [], 'r')
3974  augroup END
3975  call assert_fails('lhelpgrep quickfix', 'E926:')
3976  augroup QF_Test
3977    au! BufEnter
3978  augroup END
3979
3980  new | only
3981endfunc
3982
3983" Test for shortening/simplifying the file name when opening the
3984" quickfix window or when displaying the quickfix list
3985func Test_shorten_fname()
3986  CheckUnix
3987  %bwipe
3988  " Create a quickfix list with a absolute path filename
3989  let fname = getcwd() . '/test_quickfix.vim'
3990  call setqflist([], ' ', {'lines':[fname . ":20:Line20"], 'efm':'%f:%l:%m'})
3991  call assert_equal(fname, bufname('test_quickfix.vim'))
3992  " Opening the quickfix window should simplify the file path
3993  cwindow
3994  call assert_equal('test_quickfix.vim', bufname('test_quickfix.vim'))
3995  cclose
3996  %bwipe
3997  " Create a quickfix list with a absolute path filename
3998  call setqflist([], ' ', {'lines':[fname . ":20:Line20"], 'efm':'%f:%l:%m'})
3999  call assert_equal(fname, bufname('test_quickfix.vim'))
4000  " Displaying the quickfix list should simplify the file path
4001  silent! clist
4002  call assert_equal('test_quickfix.vim', bufname('test_quickfix.vim'))
4003  " Add a few entries for the same file with different paths and check whether
4004  " the buffer name is shortened
4005  %bwipe
4006  call setqflist([], 'f')
4007  call setqflist([{'filename' : 'test_quickfix.vim', 'lnum' : 10},
4008        \ {'filename' : '../testdir/test_quickfix.vim', 'lnum' : 20},
4009        \ {'filename' : fname, 'lnum' : 30}], ' ')
4010  copen
4011  call assert_equal(['test_quickfix.vim|10| ',
4012        \ 'test_quickfix.vim|20| ',
4013        \ 'test_quickfix.vim|30| '], getline(1, '$'))
4014  cclose
4015endfunc
4016
4017" Quickfix title tests
4018" In the below tests, 'exe "cmd"' is used to invoke the quickfix commands.
4019" Otherwise due to indentation, the title is set with spaces at the beginning
4020" of the command.
4021func Test_qftitle()
4022  call writefile(["F1:1:Line1"], 'Xerr')
4023
4024  " :cexpr
4025  exe "cexpr readfile('Xerr')"
4026  call assert_equal(":cexpr readfile('Xerr')", getqflist({'title' : 1}).title)
4027
4028  " :cgetexpr
4029  exe "cgetexpr readfile('Xerr')"
4030  call assert_equal(":cgetexpr readfile('Xerr')",
4031					\ getqflist({'title' : 1}).title)
4032
4033  " :caddexpr
4034  call setqflist([], 'f')
4035  exe "caddexpr readfile('Xerr')"
4036  call assert_equal(":caddexpr readfile('Xerr')",
4037					\ getqflist({'title' : 1}).title)
4038
4039  " :cbuffer
4040  new Xerr
4041  exe "cbuffer"
4042  call assert_equal(':cbuffer (Xerr)', getqflist({'title' : 1}).title)
4043
4044  " :cgetbuffer
4045  edit Xerr
4046  exe "cgetbuffer"
4047  call assert_equal(':cgetbuffer (Xerr)', getqflist({'title' : 1}).title)
4048
4049  " :caddbuffer
4050  call setqflist([], 'f')
4051  edit Xerr
4052  exe "caddbuffer"
4053  call assert_equal(':caddbuffer (Xerr)', getqflist({'title' : 1}).title)
4054
4055  " :cfile
4056  exe "cfile Xerr"
4057  call assert_equal(':cfile Xerr', getqflist({'title' : 1}).title)
4058
4059  " :cgetfile
4060  exe "cgetfile Xerr"
4061  call assert_equal(':cgetfile Xerr', getqflist({'title' : 1}).title)
4062
4063  " :caddfile
4064  call setqflist([], 'f')
4065  exe "caddfile Xerr"
4066  call assert_equal(':caddfile Xerr', getqflist({'title' : 1}).title)
4067
4068  " :grep
4069  set grepprg=internal
4070  exe "grep F1 Xerr"
4071  call assert_equal(':grep F1 Xerr', getqflist({'title' : 1}).title)
4072
4073  " :grepadd
4074  call setqflist([], 'f')
4075  exe "grepadd F1 Xerr"
4076  call assert_equal(':grepadd F1 Xerr', getqflist({'title' : 1}).title)
4077  set grepprg&vim
4078
4079  " :vimgrep
4080  exe "vimgrep F1 Xerr"
4081  call assert_equal(':vimgrep F1 Xerr', getqflist({'title' : 1}).title)
4082
4083  " :vimgrepadd
4084  call setqflist([], 'f')
4085  exe "vimgrepadd F1 Xerr"
4086  call assert_equal(':vimgrepadd F1 Xerr', getqflist({'title' : 1}).title)
4087
4088  call setqflist(['F1:10:L10'], ' ')
4089  call assert_equal(':setqflist()', getqflist({'title' : 1}).title)
4090
4091  call setqflist([], 'f')
4092  call setqflist(['F1:10:L10'], 'a')
4093  call assert_equal(':setqflist()', getqflist({'title' : 1}).title)
4094
4095  call setqflist([], 'f')
4096  call setqflist(['F1:10:L10'], 'r')
4097  call assert_equal(':setqflist()', getqflist({'title' : 1}).title)
4098
4099  close
4100  call delete('Xerr')
4101
4102  call setqflist([], ' ', {'title' : 'Errors'})
4103  copen
4104  call assert_equal('Errors', w:quickfix_title)
4105  call setqflist([], 'r', {'items' : [{'filename' : 'a.c', 'lnum' : 10}]})
4106  call assert_equal('Errors', w:quickfix_title)
4107  cclose
4108endfunc
4109
4110func Test_lbuffer_with_bwipe()
4111  new
4112  new
4113  augroup nasty
4114    au * * bwipe
4115  augroup END
4116  lbuffer
4117  augroup nasty
4118    au!
4119  augroup END
4120endfunc
4121
4122" Test for an autocmd freeing the quickfix/location list when cexpr/lexpr is
4123" running
4124func Xexpr_acmd_freelist(cchar)
4125  call s:setup_commands(a:cchar)
4126
4127  " This was using freed memory.
4128  augroup nasty
4129    au * * call g:Xsetlist([], 'f')
4130  augroup END
4131  Xexpr "x"
4132  augroup nasty
4133    au!
4134  augroup END
4135endfunc
4136
4137func Test_cexpr_acmd_freelist()
4138  call Xexpr_acmd_freelist('c')
4139  call Xexpr_acmd_freelist('l')
4140endfunc
4141
4142" Test for commands that create a new quickfix/location list and jump to the
4143" first error automatically.
4144func Xjumpto_first_error_test(cchar)
4145  call s:setup_commands(a:cchar)
4146
4147  call s:create_test_file('Xtestfile1')
4148  call s:create_test_file('Xtestfile2')
4149  let l = ['Xtestfile1:2:Line2', 'Xtestfile2:4:Line4']
4150
4151  " Test for cexpr/lexpr
4152  enew
4153  Xexpr l
4154  call assert_equal('Xtestfile1', @%)
4155  call assert_equal(2, line('.'))
4156
4157  " Test for cfile/lfile
4158  enew
4159  call writefile(l, 'Xerr')
4160  Xfile Xerr
4161  call assert_equal('Xtestfile1', @%)
4162  call assert_equal(2, line('.'))
4163
4164  " Test for cbuffer/lbuffer
4165  edit Xerr
4166  Xbuffer
4167  call assert_equal('Xtestfile1', @%)
4168  call assert_equal(2, line('.'))
4169
4170  call delete('Xerr')
4171  call delete('Xtestfile1')
4172  call delete('Xtestfile2')
4173endfunc
4174
4175func Test_jumpto_first_error()
4176  call Xjumpto_first_error_test('c')
4177  call Xjumpto_first_error_test('l')
4178endfunc
4179
4180" Test for a quickfix autocmd changing the quickfix/location list before
4181" jumping to the first error in the new list.
4182func Xautocmd_changelist(cchar)
4183  call s:setup_commands(a:cchar)
4184
4185  " Test for cfile/lfile
4186  call s:create_test_file('Xtestfile1')
4187  call s:create_test_file('Xtestfile2')
4188  Xexpr 'Xtestfile1:2:Line2'
4189  autocmd QuickFixCmdPost * Xolder
4190  call writefile(['Xtestfile2:4:Line4'], 'Xerr')
4191  Xfile Xerr
4192  call assert_equal('Xtestfile2', @%)
4193  call assert_equal(4, line('.'))
4194  autocmd! QuickFixCmdPost
4195
4196  " Test for cbuffer/lbuffer
4197  call g:Xsetlist([], 'f')
4198  Xexpr 'Xtestfile1:2:Line2'
4199  autocmd QuickFixCmdPost * Xolder
4200  call writefile(['Xtestfile2:4:Line4'], 'Xerr')
4201  edit Xerr
4202  Xbuffer
4203  call assert_equal('Xtestfile2', @%)
4204  call assert_equal(4, line('.'))
4205  autocmd! QuickFixCmdPost
4206
4207  " Test for cexpr/lexpr
4208  call g:Xsetlist([], 'f')
4209  Xexpr 'Xtestfile1:2:Line2'
4210  autocmd QuickFixCmdPost * Xolder
4211  Xexpr 'Xtestfile2:4:Line4'
4212  call assert_equal('Xtestfile2', @%)
4213  call assert_equal(4, line('.'))
4214  autocmd! QuickFixCmdPost
4215
4216  " The grepprg may not be set on non-Unix systems
4217  if has('unix')
4218    " Test for grep/lgrep
4219    call g:Xsetlist([], 'f')
4220    Xexpr 'Xtestfile1:2:Line2'
4221    autocmd QuickFixCmdPost * Xolder
4222    silent Xgrep Line5 Xtestfile2
4223    call assert_equal('Xtestfile2', @%)
4224    call assert_equal(5, line('.'))
4225    autocmd! QuickFixCmdPost
4226  endif
4227
4228  " Test for vimgrep/lvimgrep
4229  call g:Xsetlist([], 'f')
4230  Xexpr 'Xtestfile1:2:Line2'
4231  autocmd QuickFixCmdPost * Xolder
4232  silent Xvimgrep Line5 Xtestfile2
4233  call assert_equal('Xtestfile2', @%)
4234  call assert_equal(5, line('.'))
4235  autocmd! QuickFixCmdPost
4236
4237  " Test for autocommands clearing the quickfix list before jumping to the
4238  " first error. This should not result in an error
4239  autocmd QuickFixCmdPost * call g:Xsetlist([], 'r')
4240  let v:errmsg = ''
4241  " Test for cfile/lfile
4242  Xfile Xerr
4243  call assert_true(v:errmsg !~# 'E42:')
4244  " Test for cbuffer/lbuffer
4245  edit Xerr
4246  Xbuffer
4247  call assert_true(v:errmsg !~# 'E42:')
4248  " Test for cexpr/lexpr
4249  Xexpr 'Xtestfile2:4:Line4'
4250  call assert_true(v:errmsg !~# 'E42:')
4251  " Test for grep/lgrep
4252  " The grepprg may not be set on non-Unix systems
4253  if has('unix')
4254    silent Xgrep Line5 Xtestfile2
4255    call assert_true(v:errmsg !~# 'E42:')
4256  endif
4257  " Test for vimgrep/lvimgrep
4258  call assert_fails('silent Xvimgrep Line5 Xtestfile2', 'E480:')
4259  autocmd! QuickFixCmdPost
4260
4261  call delete('Xerr')
4262  call delete('Xtestfile1')
4263  call delete('Xtestfile2')
4264endfunc
4265
4266func Test_autocmd_changelist()
4267  call Xautocmd_changelist('c')
4268  call Xautocmd_changelist('l')
4269endfunc
4270
4271" Tests for the ':filter /pat/ clist' command
4272func Test_filter_clist()
4273  cexpr ['Xfile1:10:10:Line 10', 'Xfile2:15:15:Line 15']
4274  call assert_equal([' 2 Xfile2:15 col 15: Line 15'],
4275			\ split(execute('filter /Line 15/ clist'), "\n"))
4276  call assert_equal([' 1 Xfile1:10 col 10: Line 10'],
4277			\ split(execute('filter /Xfile1/ clist'), "\n"))
4278  call assert_equal([], split(execute('filter /abc/ clist'), "\n"))
4279
4280  call setqflist([{'module' : 'abc', 'pattern' : 'pat1'},
4281			\ {'module' : 'pqr', 'pattern' : 'pat2'}], ' ')
4282  call assert_equal([' 2 pqr:pat2:  '],
4283			\ split(execute('filter /pqr/ clist'), "\n"))
4284  call assert_equal([' 1 abc:pat1:  '],
4285			\ split(execute('filter /pat1/ clist'), "\n"))
4286endfunc
4287
4288" Tests for the "CTRL-W <CR>" command.
4289func Xview_result_split_tests(cchar)
4290  call s:setup_commands(a:cchar)
4291
4292  " Test that "CTRL-W <CR>" in a qf/ll window fails with empty list.
4293  call g:Xsetlist([])
4294  Xopen
4295  let l:win_count = winnr('$')
4296  call assert_fails('execute "normal! \<C-W>\<CR>"', 'E42:')
4297  call assert_equal(l:win_count, winnr('$'))
4298  Xclose
4299endfunc
4300
4301func Test_view_result_split()
4302  call Xview_result_split_tests('c')
4303  call Xview_result_split_tests('l')
4304endfunc
4305
4306" Test that :cc sets curswant
4307func Test_curswant()
4308  helpgrep quickfix
4309  normal! llll
4310  1cc
4311  call assert_equal(getcurpos()[4], virtcol('.'))
4312  cclose | helpclose
4313endfunc
4314
4315" Test for opening a file from the quickfix window using CTRL-W <Enter>
4316" doesn't leave an empty buffer around.
4317func Test_splitview()
4318  call s:create_test_file('Xtestfile1')
4319  call s:create_test_file('Xtestfile2')
4320  new | only
4321  let last_bufnr = bufnr('Test_sv_1', 1)
4322  let l = ['Xtestfile1:2:Line2', 'Xtestfile2:4:Line4']
4323  cgetexpr l
4324  copen
4325  let numbufs = len(getbufinfo())
4326  exe "normal \<C-W>\<CR>"
4327  copen
4328  exe "normal j\<C-W>\<CR>"
4329  " Make sure new empty buffers are not created
4330  call assert_equal(numbufs, len(getbufinfo()))
4331  " Creating a new buffer should use the next available buffer number
4332  call assert_equal(last_bufnr + 4, bufnr("Test_sv_2", 1))
4333  bwipe Test_sv_1
4334  bwipe Test_sv_2
4335  new | only
4336
4337  " When split opening files from location list window, make sure that two
4338  " windows doesn't refer to the same location list
4339  lgetexpr l
4340  let locid = getloclist(0, {'id' : 0}).id
4341  lopen
4342  exe "normal \<C-W>\<CR>"
4343  call assert_notequal(locid, getloclist(0, {'id' : 0}).id)
4344  call assert_equal(0, getloclist(0, {'winid' : 0}).winid)
4345  new | only
4346
4347  " When split opening files from a helpgrep location list window, a new help
4348  " window should be opened with a copy of the location list.
4349  lhelpgrep window
4350  let locid = getloclist(0, {'id' : 0}).id
4351  lwindow
4352  exe "normal j\<C-W>\<CR>"
4353  call assert_notequal(locid, getloclist(0, {'id' : 0}).id)
4354  call assert_equal(0, getloclist(0, {'winid' : 0}).winid)
4355  new | only
4356
4357  " Using :split or :vsplit from a quickfix window should behave like a :new
4358  " or a :vnew command
4359  copen
4360  split
4361  call assert_equal(3, winnr('$'))
4362  let l = getwininfo()
4363  call assert_equal([0, 0, 1], [l[0].quickfix, l[1].quickfix, l[2].quickfix])
4364  close
4365  copen
4366  vsplit
4367  let l = getwininfo()
4368  call assert_equal([0, 0, 1], [l[0].quickfix, l[1].quickfix, l[2].quickfix])
4369  new | only
4370
4371  call delete('Xtestfile1')
4372  call delete('Xtestfile2')
4373endfunc
4374
4375" Test for parsing entries using visual screen column
4376func Test_viscol()
4377  enew
4378  call writefile(["Col1\tCol2\tCol3"], 'Xfile1')
4379  edit Xfile1
4380
4381  " Use byte offset for column number
4382  set efm&
4383  cexpr "Xfile1:1:5:XX\nXfile1:1:9:YY\nXfile1:1:20:ZZ"
4384  call assert_equal([5, 8], [col('.'), virtcol('.')])
4385  cnext
4386  call assert_equal([9, 12], [col('.'), virtcol('.')])
4387  cnext
4388  call assert_equal([14, 20], [col('.'), virtcol('.')])
4389
4390  " Use screen column offset for column number
4391  set efm=%f:%l:%v:%m
4392  cexpr "Xfile1:1:8:XX\nXfile1:1:12:YY\nXfile1:1:20:ZZ"
4393  call assert_equal([5, 8], [col('.'), virtcol('.')])
4394  cnext
4395  call assert_equal([9, 12], [col('.'), virtcol('.')])
4396  cnext
4397  call assert_equal([14, 20], [col('.'), virtcol('.')])
4398  cexpr "Xfile1:1:6:XX\nXfile1:1:15:YY\nXfile1:1:24:ZZ"
4399  call assert_equal([5, 8], [col('.'), virtcol('.')])
4400  cnext
4401  call assert_equal([10, 16], [col('.'), virtcol('.')])
4402  cnext
4403  call assert_equal([14, 20], [col('.'), virtcol('.')])
4404
4405  enew
4406  call writefile(["Col1\täü\töß\tCol4"], 'Xfile1')
4407
4408  " Use byte offset for column number
4409  set efm&
4410  cexpr "Xfile1:1:8:XX\nXfile1:1:11:YY\nXfile1:1:16:ZZ"
4411  call assert_equal([8, 10], [col('.'), virtcol('.')])
4412  cnext
4413  call assert_equal([11, 17], [col('.'), virtcol('.')])
4414  cnext
4415  call assert_equal([16, 25], [col('.'), virtcol('.')])
4416
4417  " Use screen column offset for column number
4418  set efm=%f:%l:%v:%m
4419  cexpr "Xfile1:1:10:XX\nXfile1:1:17:YY\nXfile1:1:25:ZZ"
4420  call assert_equal([8, 10], [col('.'), virtcol('.')])
4421  cnext
4422  call assert_equal([11, 17], [col('.'), virtcol('.')])
4423  cnext
4424  call assert_equal([16, 25], [col('.'), virtcol('.')])
4425
4426  " Use screen column number with a multi-line error message
4427  enew
4428  call writefile(["à test"], 'Xfile1')
4429  set efm=%E===\ %f\ ===,%C%l:%v,%Z%m
4430  cexpr ["=== Xfile1 ===", "1:3", "errormsg"]
4431  call assert_equal('Xfile1', @%)
4432  call assert_equal([0, 1, 4, 0], getpos('.'))
4433
4434  " Repeat previous test with byte offset %c: ensure that fix to issue #7145
4435  " does not break this
4436  set efm=%E===\ %f\ ===,%C%l:%c,%Z%m
4437  cexpr ["=== Xfile1 ===", "1:3", "errormsg"]
4438  call assert_equal('Xfile1', @%)
4439  call assert_equal([0, 1, 3, 0], getpos('.'))
4440
4441  enew | only
4442  set efm&
4443  call delete('Xfile1')
4444endfunc
4445
4446" Test for the quickfix window buffer
4447func Xqfbuf_test(cchar)
4448  call s:setup_commands(a:cchar)
4449
4450  " Quickfix buffer should be reused across closing and opening a quickfix
4451  " window
4452  Xexpr "F1:10:Line10"
4453  Xopen
4454  let qfbnum = bufnr('')
4455  Xclose
4456  " Even after the quickfix window is closed, the buffer should be loaded
4457  call assert_true(bufloaded(qfbnum))
4458  call assert_true(qfbnum, g:Xgetlist({'qfbufnr' : 0}).qfbufnr)
4459  Xopen
4460  " Buffer should be reused when opening the window again
4461  call assert_equal(qfbnum, bufnr(''))
4462  Xclose
4463
4464  if a:cchar == 'l'
4465    %bwipe
4466    " For a location list, when both the file window and the location list
4467    " window for the list are closed, then the buffer should be freed.
4468    new | only
4469    lexpr "F1:10:Line10"
4470    let wid = win_getid()
4471    lopen
4472    let qfbnum = bufnr('')
4473    call assert_match(qfbnum . ' %a-  "\[Location List]"', execute('ls'))
4474    close
4475    " When the location list window is closed, the buffer name should not
4476    " change to 'Quickfix List'
4477    call assert_match(qfbnum . 'u h-  "\[Location List]"', execute('ls!'))
4478    call assert_true(bufloaded(qfbnum))
4479
4480    " After deleting a location list buffer using ":bdelete", opening the
4481    " location list window should mark the buffer as a location list buffer.
4482    exe "bdelete " . qfbnum
4483    lopen
4484    call assert_equal("quickfix", &buftype)
4485    call assert_equal(1, getwininfo(win_getid(winnr()))[0].loclist)
4486    call assert_equal(wid, getloclist(0, {'filewinid' : 0}).filewinid)
4487    call assert_false(&swapfile)
4488    lclose
4489
4490    " When the location list is cleared for the window, the buffer should be
4491    " removed
4492    call setloclist(0, [], 'f')
4493    call assert_false(bufexists(qfbnum))
4494    call assert_equal(0, getloclist(0, {'qfbufnr' : 0}).qfbufnr)
4495
4496    " When the location list is freed with the location list window open, the
4497    " location list buffer should not be lost. It should be reused when the
4498    " location list is again populated.
4499    lexpr "F1:10:Line10"
4500    lopen
4501    let wid = win_getid()
4502    let qfbnum = bufnr('')
4503    wincmd p
4504    call setloclist(0, [], 'f')
4505    lexpr "F1:10:Line10"
4506    lopen
4507    call assert_equal(wid, win_getid())
4508    call assert_equal(qfbnum, bufnr(''))
4509    lclose
4510
4511    " When the window with the location list is closed, the buffer should be
4512    " removed
4513    new | only
4514    call assert_false(bufexists(qfbnum))
4515  endif
4516endfunc
4517
4518func Test_qfbuf()
4519  call Xqfbuf_test('c')
4520  call Xqfbuf_test('l')
4521endfunc
4522
4523" If there is an autocmd to use only one window, then opening the location
4524" list window used to crash Vim.
4525func Test_winonly_autocmd()
4526  call s:create_test_file('Xtest1')
4527  " Autocmd to show only one Vim window at a time
4528  autocmd WinEnter * only
4529  new
4530  " Load the location list
4531  lexpr "Xtest1:5:Line5\nXtest1:10:Line10\nXtest1:15:Line15"
4532  let loclistid = getloclist(0, {'id' : 0}).id
4533  " Open the location list window. Only this window will be shown and the file
4534  " window is closed.
4535  lopen
4536  call assert_equal(loclistid, getloclist(0, {'id' : 0}).id)
4537  " Jump to an entry in the location list and make sure that the cursor is
4538  " positioned correctly.
4539  ll 3
4540  call assert_equal(loclistid, getloclist(0, {'id' : 0}).id)
4541  call assert_equal('Xtest1', @%)
4542  call assert_equal(15, line('.'))
4543  " Cleanup
4544  autocmd! WinEnter
4545  new | only
4546  call delete('Xtest1')
4547endfunc
4548
4549" Test to make sure that an empty quickfix buffer is not reused for loading
4550" a normal buffer.
4551func Test_empty_qfbuf()
4552  enew | only
4553  call writefile(["Test"], 'Xfile1')
4554  call setqflist([], 'f')
4555  copen | only
4556  let qfbuf = bufnr('')
4557  edit Xfile1
4558  call assert_notequal(qfbuf, bufnr(''))
4559  enew
4560  call delete('Xfile1')
4561endfunc
4562
4563" Test for the :cbelow, :cabove, :lbelow and :labove commands.
4564" And for the :cafter, :cbefore, :lafter and :lbefore commands.
4565func Xtest_below(cchar)
4566  call s:setup_commands(a:cchar)
4567
4568  " No quickfix/location list
4569  call assert_fails('Xbelow', 'E42:')
4570  call assert_fails('Xabove', 'E42:')
4571  call assert_fails('Xbefore', 'E42:')
4572  call assert_fails('Xafter', 'E42:')
4573
4574  " Empty quickfix/location list
4575  call g:Xsetlist([])
4576  call assert_fails('Xbelow', 'E42:')
4577  call assert_fails('Xabove', 'E42:')
4578  call assert_fails('Xbefore', 'E42:')
4579  call assert_fails('Xafter', 'E42:')
4580
4581  call s:create_test_file('X1')
4582  call s:create_test_file('X2')
4583  call s:create_test_file('X3')
4584  call s:create_test_file('X4')
4585
4586  " Invalid entries
4587  edit X1
4588  call g:Xsetlist(["E1", "E2"])
4589  call assert_fails('Xbelow', 'E42:')
4590  call assert_fails('Xabove', 'E42:')
4591  call assert_fails('3Xbelow', 'E42:')
4592  call assert_fails('4Xabove', 'E42:')
4593  call assert_fails('Xbefore', 'E42:')
4594  call assert_fails('Xafter', 'E42:')
4595  call assert_fails('3Xbefore', 'E42:')
4596  call assert_fails('4Xafter', 'E42:')
4597
4598  " Test the commands with various arguments
4599  Xexpr ["X1:5:3:L5", "X2:5:2:L5", "X2:10:3:L10", "X2:15:4:L15", "X3:3:5:L3"]
4600  edit +7 X2
4601  Xabove
4602  call assert_equal(['X2', 5], [@%, line('.')])
4603  call assert_fails('Xabove', 'E553:')
4604  normal 7G
4605  Xbefore
4606  call assert_equal(['X2', 5, 2], [@%, line('.'), col('.')])
4607  call assert_fails('Xbefore', 'E553:')
4608
4609  normal 2j
4610  Xbelow
4611  call assert_equal(['X2', 10], [@%, line('.')])
4612  normal 7G
4613  Xafter
4614  call assert_equal(['X2', 10, 3], [@%, line('.'), col('.')])
4615
4616  " Last error in this file
4617  Xbelow 99
4618  call assert_equal(['X2', 15], [@%, line('.')])
4619  call assert_fails('Xbelow', 'E553:')
4620  normal gg
4621  Xafter 99
4622  call assert_equal(['X2', 15, 4], [@%, line('.'), col('.')])
4623  call assert_fails('Xafter', 'E553:')
4624
4625  " First error in this file
4626  Xabove 99
4627  call assert_equal(['X2', 5], [@%, line('.')])
4628  call assert_fails('Xabove', 'E553:')
4629  normal G
4630  Xbefore 99
4631  call assert_equal(['X2', 5, 2], [@%, line('.'), col('.')])
4632  call assert_fails('Xbefore', 'E553:')
4633
4634  normal gg
4635  Xbelow 2
4636  call assert_equal(['X2', 10], [@%, line('.')])
4637  normal gg
4638  Xafter 2
4639  call assert_equal(['X2', 10, 3], [@%, line('.'), col('.')])
4640
4641  normal G
4642  Xabove 2
4643  call assert_equal(['X2', 10], [@%, line('.')])
4644  normal G
4645  Xbefore 2
4646  call assert_equal(['X2', 10, 3], [@%, line('.'), col('.')])
4647
4648  edit X4
4649  call assert_fails('Xabove', 'E42:')
4650  call assert_fails('Xbelow', 'E42:')
4651  call assert_fails('Xbefore', 'E42:')
4652  call assert_fails('Xafter', 'E42:')
4653  if a:cchar == 'l'
4654    " If a buffer has location list entries from some other window but not
4655    " from the current window, then the commands should fail.
4656    edit X1 | split | call setloclist(0, [], 'f')
4657    call assert_fails('Xabove', 'E776:')
4658    call assert_fails('Xbelow', 'E776:')
4659    call assert_fails('Xbefore', 'E776:')
4660    call assert_fails('Xafter', 'E776:')
4661    close
4662  endif
4663
4664  " Test for lines with multiple quickfix entries
4665  Xexpr ["X1:5:L5", "X2:5:1:L5_1", "X2:5:2:L5_2", "X2:5:3:L5_3",
4666	      \ "X2:10:1:L10_1", "X2:10:2:L10_2", "X2:10:3:L10_3",
4667	      \ "X2:15:1:L15_1", "X2:15:2:L15_2", "X2:15:3:L15_3", "X3:3:L3"]
4668  edit +1 X2
4669  Xbelow 2
4670  call assert_equal(['X2', 10, 1], [@%, line('.'), col('.')])
4671  normal 1G
4672  Xafter 2
4673  call assert_equal(['X2', 5, 2], [@%, line('.'), col('.')])
4674
4675  normal gg
4676  Xbelow 99
4677  call assert_equal(['X2', 15, 1], [@%, line('.'), col('.')])
4678  normal gg
4679  Xafter 99
4680  call assert_equal(['X2', 15, 3], [@%, line('.'), col('.')])
4681
4682  normal G
4683  Xabove 2
4684  call assert_equal(['X2', 10, 1], [@%, line('.'), col('.')])
4685  normal G
4686  Xbefore 2
4687  call assert_equal(['X2', 15, 2], [@%, line('.'), col('.')])
4688
4689  normal G
4690  Xabove 99
4691  call assert_equal(['X2', 5, 1], [@%, line('.'), col('.')])
4692  normal G
4693  Xbefore 99
4694  call assert_equal(['X2', 5, 1], [@%, line('.'), col('.')])
4695
4696  normal 10G
4697  Xabove
4698  call assert_equal(['X2', 5, 1], [@%, line('.'), col('.')])
4699  normal 10G$
4700  2Xbefore
4701  call assert_equal(['X2', 10, 2], [@%, line('.'), col('.')])
4702
4703  normal 10G
4704  Xbelow
4705  call assert_equal(['X2', 15, 1], [@%, line('.'), col('.')])
4706  normal 9G
4707  5Xafter
4708  call assert_equal(['X2', 15, 2], [@%, line('.'), col('.')])
4709
4710  " Invalid range
4711  if a:cchar == 'c'
4712    call assert_fails('-2cbelow', 'E16:')
4713    call assert_fails('-2cafter', 'E16:')
4714  else
4715    call assert_fails('-2lbelow', 'E16:')
4716    call assert_fails('-2lafter', 'E16:')
4717  endif
4718
4719  call delete('X1')
4720  call delete('X2')
4721  call delete('X3')
4722  call delete('X4')
4723endfunc
4724
4725func Test_cbelow()
4726  call Xtest_below('c')
4727  call Xtest_below('l')
4728endfunc
4729
4730func Test_quickfix_count()
4731  let commands = [
4732	\ 'cNext',
4733	\ 'cNfile',
4734	\ 'cabove',
4735	\ 'cbelow',
4736	\ 'cfirst',
4737	\ 'clast',
4738	\ 'cnewer',
4739	\ 'cnext',
4740	\ 'cnfile',
4741	\ 'colder',
4742	\ 'cprevious',
4743	\ 'crewind',
4744	\
4745	\ 'lNext',
4746	\ 'lNfile',
4747	\ 'labove',
4748	\ 'lbelow',
4749	\ 'lfirst',
4750	\ 'llast',
4751	\ 'lnewer',
4752	\ 'lnext',
4753	\ 'lnfile',
4754	\ 'lolder',
4755	\ 'lprevious',
4756	\ 'lrewind',
4757	\ ]
4758  for cmd in commands
4759    call assert_fails('-1' .. cmd, 'E16:')
4760    call assert_fails('.' .. cmd, 'E16:')
4761    call assert_fails('%' .. cmd, 'E16:')
4762    call assert_fails('$' .. cmd, 'E16:')
4763  endfor
4764endfunc
4765
4766" Test for aborting quickfix commands using QuickFixCmdPre
4767func Xtest_qfcmd_abort(cchar)
4768  call s:setup_commands(a:cchar)
4769
4770  call g:Xsetlist([], 'f')
4771
4772  " cexpr/lexpr
4773  let e = ''
4774  try
4775    Xexpr ["F1:10:Line10", "F2:20:Line20"]
4776  catch /.*/
4777    let e = v:exception
4778  endtry
4779  call assert_equal('AbortCmd', e)
4780  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4781
4782  " cfile/lfile
4783  call writefile(["F1:10:Line10", "F2:20:Line20"], 'Xfile1')
4784  let e = ''
4785  try
4786    Xfile Xfile1
4787  catch /.*/
4788    let e = v:exception
4789  endtry
4790  call assert_equal('AbortCmd', e)
4791  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4792  call delete('Xfile1')
4793
4794  " cgetbuffer/lgetbuffer
4795  enew!
4796  call append(0, ["F1:10:Line10", "F2:20:Line20"])
4797  let e = ''
4798  try
4799    Xgetbuffer
4800  catch /.*/
4801    let e = v:exception
4802  endtry
4803  call assert_equal('AbortCmd', e)
4804  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4805  enew!
4806
4807  " vimgrep/lvimgrep
4808  let e = ''
4809  try
4810    Xvimgrep /func/ test_quickfix.vim
4811  catch /.*/
4812    let e = v:exception
4813  endtry
4814  call assert_equal('AbortCmd', e)
4815  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4816
4817  " helpgrep/lhelpgrep
4818  let e = ''
4819  try
4820    Xhelpgrep quickfix
4821  catch /.*/
4822    let e = v:exception
4823  endtry
4824  call assert_equal('AbortCmd', e)
4825  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4826
4827  " grep/lgrep
4828  if has('unix')
4829    let e = ''
4830    try
4831      silent Xgrep func test_quickfix.vim
4832    catch /.*/
4833      let e = v:exception
4834    endtry
4835    call assert_equal('AbortCmd', e)
4836    call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4837  endif
4838endfunc
4839
4840func Test_qfcmd_abort()
4841  augroup QF_Test
4842    au!
4843    autocmd  QuickFixCmdPre * throw "AbortCmd"
4844  augroup END
4845
4846  call Xtest_qfcmd_abort('c')
4847  call Xtest_qfcmd_abort('l')
4848
4849  augroup QF_Test
4850    au!
4851  augroup END
4852endfunc
4853
4854" Test for using a file in one of the parent directories.
4855func Test_search_in_dirstack()
4856  call mkdir('Xtestdir/a/b/c', 'p')
4857  let save_cwd = getcwd()
4858  call writefile(["X1_L1", "X1_L2"], 'Xtestdir/Xfile1')
4859  call writefile(["X2_L1", "X2_L2"], 'Xtestdir/a/Xfile2')
4860  call writefile(["X3_L1", "X3_L2"], 'Xtestdir/a/b/Xfile3')
4861  call writefile(["X4_L1", "X4_L2"], 'Xtestdir/a/b/c/Xfile4')
4862
4863  let lines = "Entering dir Xtestdir\n" .
4864	      \ "Entering dir a\n" .
4865	      \ "Entering dir b\n" .
4866	      \ "Xfile2:2:X2_L2\n" .
4867	      \ "Leaving dir a\n" .
4868	      \ "Xfile1:2:X1_L2\n" .
4869	      \ "Xfile3:1:X3_L1\n" .
4870	      \ "Entering dir c\n" .
4871	      \ "Xfile4:2:X4_L2\n" .
4872	      \ "Leaving dir c\n"
4873  set efm=%DEntering\ dir\ %f,%XLeaving\ dir\ %f,%f:%l:%m
4874  cexpr lines .. "Leaving dir Xtestdir|\n" | let next = 1
4875  call assert_equal(11, getqflist({'size' : 0}).size)
4876  call assert_equal(4, getqflist({'idx' : 0}).idx)
4877  call assert_equal('X2_L2', getline('.'))
4878  call assert_equal(1, next)
4879  cnext
4880  call assert_equal(6, getqflist({'idx' : 0}).idx)
4881  call assert_equal('X1_L2', getline('.'))
4882  cnext
4883  call assert_equal(7, getqflist({'idx' : 0}).idx)
4884  call assert_equal(1, line('$'))
4885  call assert_equal('', getline(1))
4886  cnext
4887  call assert_equal(9, getqflist({'idx' : 0}).idx)
4888  call assert_equal(1, line('$'))
4889  call assert_equal('', getline(1))
4890
4891  set efm&
4892  exe 'cd ' . save_cwd
4893  call delete('Xtestdir', 'rf')
4894endfunc
4895
4896" Test for :cquit
4897func Test_cquit()
4898  " Exit Vim with a non-zero value
4899  if RunVim([], ["cquit 7"], '')
4900    call assert_equal(7, v:shell_error)
4901  endif
4902
4903  if RunVim([], ["50cquit"], '')
4904    call assert_equal(50, v:shell_error)
4905  endif
4906
4907  " Exit Vim with default value
4908  if RunVim([], ["cquit"], '')
4909    call assert_equal(1, v:shell_error)
4910  endif
4911
4912  " Exit Vim with zero value
4913  if RunVim([], ["cquit 0"], '')
4914    call assert_equal(0, v:shell_error)
4915  endif
4916
4917  " Exit Vim with negative value
4918  call assert_fails('-3cquit', 'E16:')
4919endfunc
4920
4921" Test for getting a specific item from a quickfix list
4922func Xtest_getqflist_by_idx(cchar)
4923  call s:setup_commands(a:cchar)
4924  " Empty list
4925  call assert_equal([], g:Xgetlist({'idx' : 1, 'items' : 0}).items)
4926  Xexpr ['F1:10:L10', 'F1:20:L20']
4927  let l = g:Xgetlist({'idx' : 2, 'items' : 0}).items
4928  call assert_equal(bufnr('F1'), l[0].bufnr)
4929  call assert_equal(20, l[0].lnum)
4930  call assert_equal('L20', l[0].text)
4931  call assert_equal([], g:Xgetlist({'idx' : -1, 'items' : 0}).items)
4932  call assert_equal([], g:Xgetlist({'idx' : 3, 'items' : 0}).items)
4933  %bwipe!
4934endfunc
4935
4936func Test_getqflist_by_idx()
4937  call Xtest_getqflist_by_idx('c')
4938  call Xtest_getqflist_by_idx('l')
4939endfunc
4940
4941" Test for the 'quickfixtextfunc' setting
4942func Tqfexpr(info)
4943  if a:info.quickfix
4944    let qfl = getqflist({'id' : a:info.id, 'items' : 1}).items
4945  else
4946    let qfl = getloclist(a:info.winid, {'id' : a:info.id, 'items' : 1}).items
4947  endif
4948
4949  let l = []
4950  for idx in range(a:info.start_idx - 1, a:info.end_idx - 1)
4951    let e = qfl[idx]
4952    let s = ''
4953    if e.bufnr != 0
4954      let bname = bufname(e.bufnr)
4955      let s ..= fnamemodify(bname, ':.')
4956    endif
4957    let s ..= '-'
4958    let s ..= 'L' .. string(e.lnum) .. 'C' .. string(e.col) .. '-'
4959    let s ..= e.text
4960    call add(l, s)
4961  endfor
4962
4963  return l
4964endfunc
4965
4966func Xtest_qftextfunc(cchar)
4967  call s:setup_commands(a:cchar)
4968
4969  set efm=%f:%l:%c:%m
4970  set quickfixtextfunc=Tqfexpr
4971  call assert_equal('Tqfexpr', &quickfixtextfunc)
4972  call assert_equal('',
4973        \ g:Xgetlist({'quickfixtextfunc' : 1}).quickfixtextfunc)
4974  Xexpr ['F1:10:2:green', 'F1:20:4:blue']
4975  Xwindow
4976  call assert_equal('F1-L10C2-green', getline(1))
4977  call assert_equal('F1-L20C4-blue', getline(2))
4978  Xclose
4979  set quickfixtextfunc&vim
4980  Xwindow
4981  call assert_equal('F1|10 col 2| green', getline(1))
4982  call assert_equal('F1|20 col 4| blue', getline(2))
4983  Xclose
4984  set efm&
4985  set quickfixtextfunc&
4986
4987  " Test for per list 'quickfixtextfunc' setting
4988  func PerQfText(info)
4989    if a:info.quickfix
4990      let qfl = getqflist({'id' : a:info.id, 'items' : 1}).items
4991    else
4992      let qfl = getloclist(a:info.winid, {'id' : a:info.id, 'items' : 1}).items
4993    endif
4994    if empty(qfl)
4995      return []
4996    endif
4997    let l = []
4998    for idx in range(a:info.start_idx - 1, a:info.end_idx - 1)
4999      call add(l, 'Line ' .. qfl[idx].lnum .. ', Col ' .. qfl[idx].col)
5000    endfor
5001    return l
5002  endfunc
5003  set quickfixtextfunc=Tqfexpr
5004  call g:Xsetlist([], ' ', {'quickfixtextfunc' : "PerQfText"})
5005  Xaddexpr ['F1:10:2:green', 'F1:20:4:blue']
5006  Xwindow
5007  call assert_equal('Line 10, Col 2', getline(1))
5008  call assert_equal('Line 20, Col 4', getline(2))
5009  Xclose
5010  call assert_equal(function('PerQfText'),
5011        \ g:Xgetlist({'quickfixtextfunc' : 1}).quickfixtextfunc)
5012  " Add entries to the list when the quickfix buffer is hidden
5013  Xaddexpr ['F1:30:6:red']
5014  Xwindow
5015  call assert_equal('Line 30, Col 6', getline(3))
5016  Xclose
5017  call g:Xsetlist([], 'r', {'quickfixtextfunc' : ''})
5018  call assert_equal('', g:Xgetlist({'quickfixtextfunc' : 1}).quickfixtextfunc)
5019  set quickfixtextfunc&
5020  delfunc PerQfText
5021
5022  " Non-existing function
5023  set quickfixtextfunc=Tabc
5024  call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue']", 'E117:')
5025  call assert_fails("Xwindow", 'E117:')
5026  Xclose
5027  set quickfixtextfunc&
5028
5029  " set option to a non-function
5030  set quickfixtextfunc=[10,\ 20]
5031  call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue']", 'E117:')
5032  call assert_fails("Xwindow", 'E117:')
5033  Xclose
5034  set quickfixtextfunc&
5035
5036  " set option to a function with different set of arguments
5037  func Xqftext(a, b, c)
5038    return a:a .. a:b .. a:c
5039  endfunc
5040  set quickfixtextfunc=Xqftext
5041  call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue']", 'E119:')
5042  call assert_fails("Xwindow", 'E119:')
5043  Xclose
5044
5045  " set option to a function that returns a list with non-strings
5046  func Xqftext2(d)
5047    return ['one', [], 'two']
5048  endfunc
5049  set quickfixtextfunc=Xqftext2
5050  call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue', 'F1:30:6:red']",
5051                                                                  \ 'E730:')
5052  call assert_fails('Xwindow', 'E730:')
5053  call assert_equal(['one', 'F1|20 col 4| blue', 'F1|30 col 6| red'],
5054        \ getline(1, '$'))
5055  Xclose
5056
5057  set quickfixtextfunc&
5058  delfunc Xqftext
5059  delfunc Xqftext2
5060
5061  " set the global option to a lambda function
5062  set quickfixtextfunc={d\ ->\ map(g:Xgetlist({'id'\ :\ d.id,\ 'items'\ :\ 1}).items[d.start_idx-1:d.end_idx-1],\ 'v:val.text')}
5063  Xexpr ['F1:10:2:green', 'F1:20:4:blue']
5064  Xwindow
5065  call assert_equal(['green', 'blue'], getline(1, '$'))
5066  Xclose
5067  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)
5068  set quickfixtextfunc&
5069
5070  " use a lambda function that returns an empty list
5071  set quickfixtextfunc={d\ ->\ []}
5072  Xexpr ['F1:10:2:green', 'F1:20:4:blue']
5073  Xwindow
5074  call assert_equal(['F1|10 col 2| green', 'F1|20 col 4| blue'],
5075        \ getline(1, '$'))
5076  Xclose
5077  set quickfixtextfunc&
5078
5079  " use a lambda function that returns a list with empty strings
5080  set quickfixtextfunc={d\ ->\ ['',\ '']}
5081  Xexpr ['F1:10:2:green', 'F1:20:4:blue']
5082  Xwindow
5083  call assert_equal(['F1|10 col 2| green', 'F1|20 col 4| blue'],
5084        \ getline(1, '$'))
5085  Xclose
5086  set quickfixtextfunc&
5087
5088  " set the per-quickfix list text function to a lambda function
5089  call g:Xsetlist([], ' ',
5090        \ {'quickfixtextfunc' :
5091        \   {d -> map(g:Xgetlist({'id' : d.id, 'items' : 1}).items[d.start_idx-1:d.end_idx-1],
5092        \ "'Line ' .. v:val.lnum .. ', Col ' .. v:val.col")}})
5093  Xaddexpr ['F1:10:2:green', 'F1:20:4:blue']
5094  Xwindow
5095  call assert_equal('Line 10, Col 2', getline(1))
5096  call assert_equal('Line 20, Col 4', getline(2))
5097  Xclose
5098  call assert_match("function('<lambda>\\d\\+')", string(g:Xgetlist({'quickfixtextfunc' : 1}).quickfixtextfunc))
5099  call g:Xsetlist([], 'f')
5100endfunc
5101
5102func Test_qftextfunc()
5103  call Xtest_qftextfunc('c')
5104  call Xtest_qftextfunc('l')
5105endfunc
5106
5107" Running :lhelpgrep command more than once in a help window, doesn't jump to
5108" the help topic
5109func Test_lhelpgrep_from_help_window()
5110  call mkdir('Xtestdir/doc', 'p')
5111  call writefile(['window'], 'Xtestdir/doc/a.txt')
5112  call writefile(['buffer'], 'Xtestdir/doc/b.txt')
5113  let save_rtp = &rtp
5114  let &rtp = 'Xtestdir'
5115  lhelpgrep window
5116  lhelpgrep buffer
5117  call assert_equal('b.txt', fnamemodify(@%, ":p:t"))
5118  lhelpgrep window
5119  call assert_equal('a.txt', fnamemodify(@%, ":p:t"))
5120  let &rtp = save_rtp
5121  call delete('Xtestdir', 'rf')
5122  new | only!
5123endfunc
5124
5125" Test for the crash fixed by 7.3.715
5126func Test_setloclist_crash()
5127  %bw!
5128  let g:BufNum = bufnr()
5129  augroup QF_Test
5130    au!
5131    au BufUnload * call setloclist(0, [{'bufnr':g:BufNum, 'lnum':1, 'col':1, 'text': 'tango down'}])
5132  augroup END
5133
5134  try
5135    lvimgrep /.*/ *.mak
5136  catch /E926:/
5137  endtry
5138  call assert_equal('tango down', getloclist(0, {'items' : 0}).items[0].text)
5139  call assert_equal(1, getloclist(0, {'size' : 0}).size)
5140
5141  augroup QF_Test
5142    au!
5143  augroup END
5144  unlet g:BufNum
5145  %bw!
5146endfunc
5147
5148" vim: shiftwidth=2 sts=2 expandtab
5149