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_caddbuffer_to_empty()
1434  helpgr quickfix
1435  call setqflist([], 'r')
1436  cad
1437  try
1438    cn
1439  catch
1440    " number of matches is unknown
1441    call assert_true(v:exception =~ 'E553:')
1442  endtry
1443  quit!
1444endfunc
1445
1446func Test_cgetexpr_works()
1447  " this must not crash Vim
1448  cgetexpr [$x]
1449  lgetexpr [$x]
1450endfunc
1451
1452" Tests for the setqflist() and setloclist() functions
1453func SetXlistTests(cchar, bnum)
1454  call s:setup_commands(a:cchar)
1455
1456  call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 1},
1457	      \  {'bufnr': a:bnum, 'lnum': 2}])
1458  let l = g:Xgetlist()
1459  call assert_equal(2, len(l))
1460  call assert_equal(2, l[1].lnum)
1461
1462  Xnext
1463  call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 3}], 'a')
1464  let l = g:Xgetlist()
1465  call assert_equal(3, len(l))
1466  Xnext
1467  call assert_equal(3, line('.'))
1468
1469  " Appending entries to the list should not change the cursor position
1470  " in the quickfix window
1471  Xwindow
1472  1
1473  call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 4},
1474	      \  {'bufnr': a:bnum, 'lnum': 5}], 'a')
1475  call assert_equal(1, line('.'))
1476  close
1477
1478  call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 3},
1479	      \  {'bufnr': a:bnum, 'lnum': 4},
1480	      \  {'bufnr': a:bnum, 'lnum': 5}], 'r')
1481  let l = g:Xgetlist()
1482  call assert_equal(3, len(l))
1483  call assert_equal(5, l[2].lnum)
1484
1485  call g:Xsetlist([])
1486  let l = g:Xgetlist()
1487  call assert_equal(0, len(l))
1488
1489  " Tests for setting the 'valid' flag
1490  call g:Xsetlist([{'bufnr':a:bnum, 'lnum':4, 'valid':0}])
1491  Xwindow
1492  call assert_equal(1, winnr('$'))
1493  let l = g:Xgetlist()
1494  call g:Xsetlist(l)
1495  call assert_equal(0, g:Xgetlist()[0].valid)
1496  " Adding a non-valid entry should not mark the list as having valid entries
1497  call g:Xsetlist([{'bufnr':a:bnum, 'lnum':5, 'valid':0}], 'a')
1498  Xwindow
1499  call assert_equal(1, winnr('$'))
1500
1501  " :cnext/:cprev should still work even with invalid entries in the list
1502  let l = [{'bufnr' : a:bnum, 'lnum' : 1, 'text' : '1', 'valid' : 0},
1503	      \ {'bufnr' : a:bnum, 'lnum' : 2, 'text' : '2', 'valid' : 0}]
1504  call g:Xsetlist(l)
1505  Xnext
1506  call assert_equal(2, g:Xgetlist({'idx' : 0}).idx)
1507  Xprev
1508  call assert_equal(1, g:Xgetlist({'idx' : 0}).idx)
1509  " :cnext/:cprev should still work after appending invalid entries to an
1510  " empty list
1511  call g:Xsetlist([])
1512  call g:Xsetlist(l, 'a')
1513  Xnext
1514  call assert_equal(2, g:Xgetlist({'idx' : 0}).idx)
1515  Xprev
1516  call assert_equal(1, g:Xgetlist({'idx' : 0}).idx)
1517
1518  call g:Xsetlist([{'text':'Text1', 'valid':1}])
1519  Xwindow
1520  call assert_equal(2, winnr('$'))
1521  Xclose
1522  let save_efm = &efm
1523  set efm=%m
1524  Xgetexpr 'TestMessage'
1525  let l = g:Xgetlist()
1526  call g:Xsetlist(l)
1527  call assert_equal(1, g:Xgetlist()[0].valid)
1528  let &efm = save_efm
1529
1530  " Error cases:
1531  " Refer to a non-existing buffer and pass a non-dictionary type
1532  call assert_fails("call g:Xsetlist([{'bufnr':998, 'lnum':4}," .
1533	      \ " {'bufnr':999, 'lnum':5}])", 'E92:')
1534  call g:Xsetlist([[1, 2,3]])
1535  call assert_equal(0, len(g:Xgetlist()))
1536  call assert_fails('call g:Xsetlist([], [])', 'E928:')
1537endfunc
1538
1539func Test_setqflist()
1540  new Xtestfile | only
1541  let bnum = bufnr('%')
1542  call setline(1, range(1,5))
1543
1544  call SetXlistTests('c', bnum)
1545  call SetXlistTests('l', bnum)
1546
1547  enew!
1548  call delete('Xtestfile')
1549endfunc
1550
1551func Xlist_empty_middle(cchar)
1552  call s:setup_commands(a:cchar)
1553
1554  " create three quickfix lists
1555  let @/ = 'Test_'
1556  Xvimgrep // test_quickfix.vim
1557  let testlen = len(g:Xgetlist())
1558  call assert_true(testlen > 0)
1559  Xvimgrep empty test_quickfix.vim
1560  call assert_true(len(g:Xgetlist()) > 0)
1561  Xvimgrep matches test_quickfix.vim
1562  let matchlen = len(g:Xgetlist())
1563  call assert_true(matchlen > 0)
1564  Xolder
1565  " make the middle list empty
1566  call g:Xsetlist([], 'r')
1567  call assert_true(len(g:Xgetlist()) == 0)
1568  Xolder
1569  call assert_equal(testlen, len(g:Xgetlist()))
1570  Xnewer
1571  Xnewer
1572  call assert_equal(matchlen, len(g:Xgetlist()))
1573endfunc
1574
1575func Test_setqflist_empty_middle()
1576  call Xlist_empty_middle('c')
1577  call Xlist_empty_middle('l')
1578endfunc
1579
1580func Xlist_empty_older(cchar)
1581  call s:setup_commands(a:cchar)
1582
1583  " create three quickfix lists
1584  Xvimgrep one test_quickfix.vim
1585  let onelen = len(g:Xgetlist())
1586  call assert_true(onelen > 0)
1587  Xvimgrep two test_quickfix.vim
1588  let twolen = len(g:Xgetlist())
1589  call assert_true(twolen > 0)
1590  Xvimgrep three test_quickfix.vim
1591  let threelen = len(g:Xgetlist())
1592  call assert_true(threelen > 0)
1593  Xolder 2
1594  " make the first list empty, check the others didn't change
1595  call g:Xsetlist([], 'r')
1596  call assert_true(len(g:Xgetlist()) == 0)
1597  Xnewer
1598  call assert_equal(twolen, len(g:Xgetlist()))
1599  Xnewer
1600  call assert_equal(threelen, len(g:Xgetlist()))
1601endfunc
1602
1603func Test_setqflist_empty_older()
1604  call Xlist_empty_older('c')
1605  call Xlist_empty_older('l')
1606endfunc
1607
1608func XquickfixSetListWithAct(cchar)
1609  call s:setup_commands(a:cchar)
1610
1611  let list1 = [{'filename': 'fnameA', 'text': 'A'},
1612          \    {'filename': 'fnameB', 'text': 'B'}]
1613  let list2 = [{'filename': 'fnameC', 'text': 'C'},
1614          \    {'filename': 'fnameD', 'text': 'D'},
1615          \    {'filename': 'fnameE', 'text': 'E'}]
1616
1617  " {action} is unspecified.  Same as specifying ' '.
1618  new | only
1619  silent! Xnewer 99
1620  call g:Xsetlist(list1)
1621  call g:Xsetlist(list2)
1622  let li = g:Xgetlist()
1623  call assert_equal(3, len(li))
1624  call assert_equal('C', li[0]['text'])
1625  call assert_equal('D', li[1]['text'])
1626  call assert_equal('E', li[2]['text'])
1627  silent! Xolder
1628  let li = g:Xgetlist()
1629  call assert_equal(2, len(li))
1630  call assert_equal('A', li[0]['text'])
1631  call assert_equal('B', li[1]['text'])
1632
1633  " {action} is specified ' '.
1634  new | only
1635  silent! Xnewer 99
1636  call g:Xsetlist(list1)
1637  call g:Xsetlist(list2, ' ')
1638  let li = g:Xgetlist()
1639  call assert_equal(3, len(li))
1640  call assert_equal('C', li[0]['text'])
1641  call assert_equal('D', li[1]['text'])
1642  call assert_equal('E', li[2]['text'])
1643  silent! Xolder
1644  let li = g:Xgetlist()
1645  call assert_equal(2, len(li))
1646  call assert_equal('A', li[0]['text'])
1647  call assert_equal('B', li[1]['text'])
1648
1649  " {action} is specified 'a'.
1650  new | only
1651  silent! Xnewer 99
1652  call g:Xsetlist(list1)
1653  call g:Xsetlist(list2, 'a')
1654  let li = g:Xgetlist()
1655  call assert_equal(5, len(li))
1656  call assert_equal('A', li[0]['text'])
1657  call assert_equal('B', li[1]['text'])
1658  call assert_equal('C', li[2]['text'])
1659  call assert_equal('D', li[3]['text'])
1660  call assert_equal('E', li[4]['text'])
1661
1662  " {action} is specified 'r'.
1663  new | only
1664  silent! Xnewer 99
1665  call g:Xsetlist(list1)
1666  call g:Xsetlist(list2, 'r')
1667  let li = g:Xgetlist()
1668  call assert_equal(3, len(li))
1669  call assert_equal('C', li[0]['text'])
1670  call assert_equal('D', li[1]['text'])
1671  call assert_equal('E', li[2]['text'])
1672
1673  " Test for wrong value.
1674  new | only
1675  call assert_fails("call g:Xsetlist(0)", 'E714:')
1676  call assert_fails("call g:Xsetlist(list1, '')", 'E927:')
1677  call assert_fails("call g:Xsetlist(list1, 'aa')", 'E927:')
1678  call assert_fails("call g:Xsetlist(list1, ' a')", 'E927:')
1679  call assert_fails("call g:Xsetlist(list1, 0)", 'E928:')
1680endfunc
1681
1682func Test_setqflist_invalid_nr()
1683  " The following command used to crash Vim
1684  eval []->setqflist(' ', {'nr' : $XXX_DOES_NOT_EXIST})
1685endfunc
1686
1687func Test_setqflist_user_sets_buftype()
1688  call setqflist([{'text': 'foo'}, {'text': 'bar'}])
1689  set buftype=quickfix
1690  call setqflist([], 'a')
1691  enew
1692endfunc
1693
1694func Test_quickfix_set_list_with_act()
1695  call XquickfixSetListWithAct('c')
1696  call XquickfixSetListWithAct('l')
1697endfunc
1698
1699func XLongLinesTests(cchar)
1700  let l = g:Xgetlist()
1701
1702  call assert_equal(4, len(l))
1703  call assert_equal(1, l[0].lnum)
1704  call assert_equal(1, l[0].col)
1705  call assert_equal(1975, len(l[0].text))
1706  call assert_equal(2, l[1].lnum)
1707  call assert_equal(1, l[1].col)
1708  call assert_equal(4070, len(l[1].text))
1709  call assert_equal(3, l[2].lnum)
1710  call assert_equal(1, l[2].col)
1711  call assert_equal(4070, len(l[2].text))
1712  call assert_equal(4, l[3].lnum)
1713  call assert_equal(1, l[3].col)
1714  call assert_equal(10, len(l[3].text))
1715
1716  call g:Xsetlist([], 'r')
1717endfunc
1718
1719func s:long_lines_tests(cchar)
1720  call s:setup_commands(a:cchar)
1721
1722  let testfile = 'samples/quickfix.txt'
1723
1724  " file
1725  exe 'Xgetfile' testfile
1726  call XLongLinesTests(a:cchar)
1727
1728  " list
1729  Xexpr readfile(testfile)
1730  call XLongLinesTests(a:cchar)
1731
1732  " string
1733  Xexpr join(readfile(testfile), "\n")
1734  call XLongLinesTests(a:cchar)
1735
1736  " buffer
1737  exe 'edit' testfile
1738  exe 'Xbuffer' bufnr('%')
1739  call XLongLinesTests(a:cchar)
1740endfunc
1741
1742func Test_long_lines()
1743  call s:long_lines_tests('c')
1744  call s:long_lines_tests('l')
1745endfunc
1746
1747func s:create_test_file(filename)
1748  let l = []
1749  for i in range(1, 20)
1750      call add(l, 'Line' . i)
1751  endfor
1752  call writefile(l, a:filename)
1753endfunc
1754
1755func Test_switchbuf()
1756  call s:create_test_file('Xqftestfile1')
1757  call s:create_test_file('Xqftestfile2')
1758  call s:create_test_file('Xqftestfile3')
1759
1760  new | only
1761  edit Xqftestfile1
1762  let file1_winid = win_getid()
1763  new Xqftestfile2
1764  let file2_winid = win_getid()
1765  cgetexpr ['Xqftestfile1:5:Line5',
1766		\ 'Xqftestfile1:6:Line6',
1767		\ 'Xqftestfile2:10:Line10',
1768		\ 'Xqftestfile2:11:Line11',
1769		\ 'Xqftestfile3:15:Line15',
1770		\ 'Xqftestfile3:16:Line16']
1771
1772  new
1773  let winid = win_getid()
1774  cfirst | cnext
1775  call assert_equal(winid, win_getid())
1776  2cnext
1777  call assert_equal(winid, win_getid())
1778  2cnext
1779  call assert_equal(winid, win_getid())
1780
1781  " Test for 'switchbuf' set to search for files in windows in the current
1782  " tabpage and jump to an existing window (if present)
1783  set switchbuf=useopen
1784  enew
1785  cfirst | cnext
1786  call assert_equal(file1_winid, win_getid())
1787  2cnext
1788  call assert_equal(file2_winid, win_getid())
1789  2cnext
1790  call assert_equal(file2_winid, win_getid())
1791
1792  " Test for 'switchbuf' set to search for files in tabpages and jump to an
1793  " existing tabpage (if present)
1794  enew | only
1795  set switchbuf=usetab
1796  tabedit Xqftestfile1
1797  tabedit Xqftestfile2
1798  tabedit Xqftestfile3
1799  tabfirst
1800  cfirst | cnext
1801  call assert_equal(2, tabpagenr())
1802  2cnext
1803  call assert_equal(3, tabpagenr())
1804  6cnext
1805  call assert_equal(4, tabpagenr())
1806  2cpfile
1807  call assert_equal(2, tabpagenr())
1808  2cnfile
1809  call assert_equal(4, tabpagenr())
1810  tabfirst | tabonly | enew
1811
1812  " Test for 'switchbuf' set to open a new window for every file
1813  set switchbuf=split
1814  cfirst | cnext
1815  call assert_equal(1, winnr('$'))
1816  cnext | cnext
1817  call assert_equal(2, winnr('$'))
1818  cnext | cnext
1819  call assert_equal(3, winnr('$'))
1820
1821  " Test for 'switchbuf' set to open a new tabpage for every file
1822  set switchbuf=newtab
1823  enew | only
1824  cfirst | cnext
1825  call assert_equal(1, tabpagenr('$'))
1826  cnext | cnext
1827  call assert_equal(2, tabpagenr('$'))
1828  cnext | cnext
1829  call assert_equal(3, tabpagenr('$'))
1830  tabfirst | enew | tabonly | only
1831
1832  set switchbuf=uselast
1833  split
1834  let last_winid = win_getid()
1835  copen
1836  exe "normal 1G\<CR>"
1837  call assert_equal(last_winid, win_getid())
1838  enew | only
1839
1840  " With an empty 'switchbuf', jumping to a quickfix entry should open the
1841  " file in an existing window (if present)
1842  set switchbuf=
1843  edit Xqftestfile1
1844  let file1_winid = win_getid()
1845  new Xqftestfile2
1846  let file2_winid = win_getid()
1847  copen
1848  exe "normal 1G\<CR>"
1849  call assert_equal(file1_winid, win_getid())
1850  copen
1851  exe "normal 3G\<CR>"
1852  call assert_equal(file2_winid, win_getid())
1853  copen | only
1854  exe "normal 5G\<CR>"
1855  call assert_equal(2, winnr('$'))
1856  call assert_equal(1, bufwinnr('Xqftestfile3'))
1857
1858  " If only quickfix window is open in the current tabpage, jumping to an
1859  " entry with 'switchbuf' set to 'usetab' should search in other tabpages.
1860  enew | only
1861  set switchbuf=usetab
1862  tabedit Xqftestfile1
1863  tabedit Xqftestfile2
1864  tabedit Xqftestfile3
1865  tabfirst
1866  copen | only
1867  clast
1868  call assert_equal(4, tabpagenr())
1869  tabfirst | tabonly | enew | only
1870
1871  " Jumping to a file that is not present in any of the tabpages and the
1872  " current tabpage doesn't have any usable windows, should open it in a new
1873  " window in the current tabpage.
1874  copen | only
1875  cfirst
1876  call assert_equal(1, tabpagenr())
1877  call assert_equal('Xqftestfile1', @%)
1878
1879  " If opening a file changes 'switchbuf', then the new value should be
1880  " retained.
1881  set modeline&vim
1882  call writefile(["vim: switchbuf=split"], 'Xqftestfile1')
1883  enew | only
1884  set switchbuf&vim
1885  cexpr "Xqftestfile1:1:10"
1886  call assert_equal('split', &switchbuf)
1887  call writefile(["vim: switchbuf=usetab"], 'Xqftestfile1')
1888  enew | only
1889  set switchbuf=useopen
1890  cexpr "Xqftestfile1:1:10"
1891  call assert_equal('usetab', &switchbuf)
1892  call writefile(["vim: switchbuf&vim"], 'Xqftestfile1')
1893  enew | only
1894  set switchbuf=useopen
1895  cexpr "Xqftestfile1:1:10"
1896  call assert_equal('', &switchbuf)
1897
1898  call delete('Xqftestfile1')
1899  call delete('Xqftestfile2')
1900  call delete('Xqftestfile3')
1901  set switchbuf&vim
1902
1903  enew | only
1904endfunc
1905
1906func Xadjust_qflnum(cchar)
1907  call s:setup_commands(a:cchar)
1908
1909  enew | only
1910
1911  let fname = 'Xqftestfile' . a:cchar
1912  call s:create_test_file(fname)
1913  exe 'edit ' . fname
1914
1915  Xgetexpr [fname . ':5:Line5',
1916	      \ fname . ':10:Line10',
1917	      \ fname . ':15:Line15',
1918	      \ fname . ':20:Line20']
1919
1920  6,14delete
1921  call append(6, ['Buffer', 'Window'])
1922
1923  let l = g:Xgetlist()
1924  call assert_equal(5, l[0].lnum)
1925  call assert_equal(6, l[2].lnum)
1926  call assert_equal(13, l[3].lnum)
1927
1928  " If a file doesn't have any quickfix entries, then deleting lines in the
1929  " file should not update the quickfix list
1930  call g:Xsetlist([], 'f')
1931  1,2delete
1932  call assert_equal([], g:Xgetlist())
1933
1934  enew!
1935  call delete(fname)
1936endfunc
1937
1938func Test_adjust_lnum()
1939  call setloclist(0, [])
1940  call Xadjust_qflnum('c')
1941  call setqflist([])
1942  call Xadjust_qflnum('l')
1943endfunc
1944
1945" Tests for the :grep/:lgrep and :grepadd/:lgrepadd commands
1946func s:test_xgrep(cchar)
1947  call s:setup_commands(a:cchar)
1948
1949  " The following lines are used for the grep test. Don't remove.
1950  " Grep_Test_Text: Match 1
1951  " Grep_Test_Text: Match 2
1952  " GrepAdd_Test_Text: Match 1
1953  " GrepAdd_Test_Text: Match 2
1954  enew! | only
1955  set makeef&vim
1956  silent Xgrep Grep_Test_Text: test_quickfix.vim
1957  call assert_true(len(g:Xgetlist()) == 5)
1958  Xopen
1959  call assert_true(w:quickfix_title =~ '^:grep')
1960  Xclose
1961  enew
1962  set makeef=Temp_File_##
1963  silent Xgrepadd GrepAdd_Test_Text: test_quickfix.vim
1964  call assert_true(len(g:Xgetlist()) == 9)
1965
1966  " Try with 'grepprg' set to 'internal'
1967  set grepprg=internal
1968  silent Xgrep Grep_Test_Text: test_quickfix.vim
1969  silent Xgrepadd GrepAdd_Test_Text: test_quickfix.vim
1970  call assert_true(len(g:Xgetlist()) == 9)
1971  set grepprg&vim
1972
1973  call writefile(['Vim'], 'XtestTempFile')
1974  set makeef=XtestTempFile
1975  silent Xgrep Grep_Test_Text: test_quickfix.vim
1976  call assert_equal(5, len(g:Xgetlist()))
1977  call assert_false(filereadable('XtestTempFile'))
1978  set makeef&vim
1979endfunc
1980
1981func Test_grep()
1982  " The grepprg may not be set on non-Unix systems
1983  CheckUnix
1984
1985  call s:test_xgrep('c')
1986  call s:test_xgrep('l')
1987endfunc
1988
1989func Test_two_windows()
1990  " Use one 'errorformat' for two windows.  Add an expression to each of them,
1991  " make sure they each keep their own state.
1992  set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f'
1993  call mkdir('Xone/a', 'p')
1994  call mkdir('Xtwo/a', 'p')
1995  let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7']
1996  call writefile(lines, 'Xone/a/one.txt')
1997  call writefile(lines, 'Xtwo/a/two.txt')
1998
1999  new one
2000  let one_id = win_getid()
2001  lexpr ""
2002  new two
2003  let two_id = win_getid()
2004  lexpr ""
2005
2006  laddexpr "Entering dir 'Xtwo/a'"
2007  call win_gotoid(one_id)
2008  laddexpr "Entering dir 'Xone/a'"
2009  call win_gotoid(two_id)
2010  laddexpr 'two.txt:5:two two two'
2011  call win_gotoid(one_id)
2012  laddexpr 'one.txt:3:one one one'
2013
2014  let loc_one = getloclist(one_id)
2015  call assert_equal('Xone/a/one.txt', bufname(loc_one[1].bufnr))
2016  call assert_equal(3, loc_one[1].lnum)
2017
2018  let loc_two = getloclist(two_id)
2019  call assert_equal('Xtwo/a/two.txt', bufname(loc_two[1].bufnr))
2020  call assert_equal(5, loc_two[1].lnum)
2021
2022  call win_gotoid(one_id)
2023  bwipe!
2024  call win_gotoid(two_id)
2025  bwipe!
2026  call delete('Xone', 'rf')
2027  call delete('Xtwo', 'rf')
2028endfunc
2029
2030func XbottomTests(cchar)
2031  call s:setup_commands(a:cchar)
2032
2033  " Calling lbottom without any errors should fail
2034  if a:cchar == 'l'
2035      call assert_fails('lbottom', 'E776:')
2036  endif
2037
2038  call g:Xsetlist([{'filename': 'foo', 'lnum': 42}])
2039  Xopen
2040  let wid = win_getid()
2041  call assert_equal(1, line('.'))
2042  wincmd w
2043  call g:Xsetlist([{'filename': 'var', 'lnum': 24}], 'a')
2044  Xbottom
2045  call win_gotoid(wid)
2046  call assert_equal(2, line('.'))
2047  Xclose
2048endfunc
2049
2050" Tests for the :cbottom and :lbottom commands
2051func Test_cbottom()
2052  call XbottomTests('c')
2053  call XbottomTests('l')
2054endfunc
2055
2056func HistoryTest(cchar)
2057  call s:setup_commands(a:cchar)
2058
2059  " clear all lists after the first one, then replace the first one.
2060  call g:Xsetlist([])
2061  call assert_fails('Xolder 99', 'E380:')
2062  let entry = {'filename': 'foo', 'lnum': 42}
2063  call g:Xsetlist([entry], 'r')
2064  call g:Xsetlist([entry, entry])
2065  call g:Xsetlist([entry, entry, entry])
2066  let res = split(execute(a:cchar . 'hist'), "\n")
2067  call assert_equal(3, len(res))
2068  let common = 'errors     :set' . (a:cchar == 'c' ? 'qf' : 'loc') . 'list()'
2069  call assert_equal('  error list 1 of 3; 1 ' . common, res[0])
2070  call assert_equal('  error list 2 of 3; 2 ' . common, res[1])
2071  call assert_equal('> error list 3 of 3; 3 ' . common, res[2])
2072
2073  " Test for changing the quickfix lists
2074  call assert_equal(3, g:Xgetlist({'nr' : 0}).nr)
2075  exe '1' . a:cchar . 'hist'
2076  call assert_equal(1, g:Xgetlist({'nr' : 0}).nr)
2077  exe '3' . a:cchar . 'hist'
2078  call assert_equal(3, g:Xgetlist({'nr' : 0}).nr)
2079  call assert_fails('-2' . a:cchar . 'hist', 'E16:')
2080  call assert_fails('4' . a:cchar . 'hist', 'E16:')
2081
2082  call g:Xsetlist([], 'f')
2083  let l = split(execute(a:cchar . 'hist'), "\n")
2084  call assert_equal('No entries', l[0])
2085  if a:cchar == 'c'
2086    call assert_fails('4chist', 'E16:')
2087  else
2088    call assert_fails('4lhist', 'E776:')
2089  endif
2090
2091  " An empty list should still show the stack history
2092  call g:Xsetlist([])
2093  let res = split(execute(a:cchar . 'hist'), "\n")
2094  call assert_equal('> error list 1 of 1; 0 ' . common, res[0])
2095
2096  call g:Xsetlist([], 'f')
2097endfunc
2098
2099func Test_history()
2100  call HistoryTest('c')
2101  call HistoryTest('l')
2102endfunc
2103
2104func Test_duplicate_buf()
2105  " make sure we can get the highest buffer number
2106  edit DoesNotExist
2107  edit DoesNotExist2
2108  let last_buffer = bufnr("$")
2109
2110  " make sure only one buffer is created
2111  call writefile(['this one', 'that one'], 'Xgrepthis')
2112  vimgrep one Xgrepthis
2113  vimgrep one Xgrepthis
2114  call assert_equal(last_buffer + 1, bufnr("$"))
2115
2116  call delete('Xgrepthis')
2117endfunc
2118
2119" Quickfix/Location list set/get properties tests
2120func Xproperty_tests(cchar)
2121  call s:setup_commands(a:cchar)
2122
2123  " Error cases
2124  call assert_fails('call g:Xgetlist(99)', 'E715:')
2125  call assert_fails('call g:Xsetlist(99)', 'E714:')
2126  call assert_fails('call g:Xsetlist([], "a", [])', 'E715:')
2127
2128  " Set and get the title
2129  call g:Xsetlist([])
2130  Xopen
2131  wincmd p
2132  call g:Xsetlist([{'filename':'foo', 'lnum':27}])
2133  let s = g:Xsetlist([], 'a', {'title' : 'Sample'})
2134  call assert_equal(0, s)
2135  let d = g:Xgetlist({"title":1})
2136  call assert_equal('Sample', d.title)
2137  " Try setting title to a non-string value
2138  call assert_equal(-1, g:Xsetlist([], 'a', {'title' : ['Test']}))
2139  call assert_equal('Sample', g:Xgetlist({"title":1}).title)
2140
2141  Xopen
2142  call assert_equal('Sample', w:quickfix_title)
2143  Xclose
2144
2145  " Tests for action argument
2146  silent! Xolder 999
2147  let qfnr = g:Xgetlist({'all':1}).nr
2148  call g:Xsetlist([], 'r', {'title' : 'N1'})
2149  call assert_equal('N1', g:Xgetlist({'all':1}).title)
2150  call g:Xsetlist([], ' ', {'title' : 'N2'})
2151  call assert_equal(qfnr + 1, g:Xgetlist({'all':1}).nr)
2152
2153  let res = g:Xgetlist({'nr': 0})
2154  call assert_equal(qfnr + 1, res.nr)
2155  call assert_equal(['nr'], keys(res))
2156
2157  call g:Xsetlist([], ' ', {'title' : 'N3'})
2158  call assert_equal('N2', g:Xgetlist({'nr':2, 'title':1}).title)
2159
2160  " Changing the title of an earlier quickfix list
2161  call g:Xsetlist([], 'r', {'title' : 'NewTitle', 'nr' : 2})
2162  call assert_equal('NewTitle', g:Xgetlist({'nr':2, 'title':1}).title)
2163
2164  " Changing the title of an invalid quickfix list
2165  call assert_equal(-1, g:Xsetlist([], ' ',
2166        \ {'title' : 'SomeTitle', 'nr' : 99}))
2167  call assert_equal(-1, g:Xsetlist([], ' ',
2168        \ {'title' : 'SomeTitle', 'nr' : 'abc'}))
2169
2170  if a:cchar == 'c'
2171    copen
2172    call assert_equal({'winid':win_getid()}, getqflist({'winid':1}))
2173    cclose
2174  endif
2175
2176  " Invalid arguments
2177  call assert_fails('call g:Xgetlist([])', 'E715:')
2178  call assert_fails('call g:Xsetlist([], "a", [])', 'E715:')
2179  let s = g:Xsetlist([], 'a', {'abc':1})
2180  call assert_equal(-1, s)
2181
2182  call assert_equal({}, g:Xgetlist({'abc':1}))
2183  call assert_equal('', g:Xgetlist({'nr':99, 'title':1}).title)
2184  call assert_equal('', g:Xgetlist({'nr':[], 'title':1}).title)
2185
2186  if a:cchar == 'l'
2187    call assert_equal({}, getloclist(99, {'title': 1}))
2188  endif
2189
2190  " Context related tests
2191  let s = g:Xsetlist([], 'a', {'context':[1,2,3]})
2192  call assert_equal(0, s)
2193  call test_garbagecollect_now()
2194  let d = g:Xgetlist({'context':1})
2195  call assert_equal([1,2,3], d.context)
2196  call g:Xsetlist([], 'a', {'context':{'color':'green'}})
2197  let d = g:Xgetlist({'context':1})
2198  call assert_equal({'color':'green'}, d.context)
2199  call g:Xsetlist([], 'a', {'context':"Context info"})
2200  let d = g:Xgetlist({'context':1})
2201  call assert_equal("Context info", d.context)
2202  call g:Xsetlist([], 'a', {'context':246})
2203  let d = g:Xgetlist({'context':1})
2204  call assert_equal(246, d.context)
2205  " set other Vim data types as context
2206  call g:Xsetlist([], 'a', {'context' : test_null_blob()})
2207  if has('channel')
2208    call g:Xsetlist([], 'a', {'context' : test_null_channel()})
2209  endif
2210  if has('job')
2211    call g:Xsetlist([], 'a', {'context' : test_null_job()})
2212  endif
2213  call g:Xsetlist([], 'a', {'context' : test_null_function()})
2214  call g:Xsetlist([], 'a', {'context' : test_null_partial()})
2215  call g:Xsetlist([], 'a', {'context' : ''})
2216  call test_garbagecollect_now()
2217  if a:cchar == 'l'
2218    " Test for copying context across two different location lists
2219    new | only
2220    let w1_id = win_getid()
2221    let l = [1]
2222    call setloclist(0, [], 'a', {'context':l})
2223    new
2224    let w2_id = win_getid()
2225    call add(l, 2)
2226    call assert_equal([1, 2], getloclist(w1_id, {'context':1}).context)
2227    call assert_equal([1, 2], getloclist(w2_id, {'context':1}).context)
2228    unlet! l
2229    call assert_equal([1, 2], getloclist(w2_id, {'context':1}).context)
2230    only
2231    call setloclist(0, [], 'f')
2232    call assert_equal('', getloclist(0, {'context':1}).context)
2233  endif
2234
2235  " Test for changing the context of previous quickfix lists
2236  call g:Xsetlist([], 'f')
2237  Xexpr "One"
2238  Xexpr "Two"
2239  Xexpr "Three"
2240  call g:Xsetlist([], 'r', {'context' : [1], 'nr' : 1})
2241  call g:Xsetlist([], 'a', {'context' : [2], 'nr' : 2})
2242  " Also, check for setting the context using quickfix list number zero.
2243  call g:Xsetlist([], 'r', {'context' : [3], 'nr' : 0})
2244  call test_garbagecollect_now()
2245  let l = g:Xgetlist({'nr' : 1, 'context' : 1})
2246  call assert_equal([1], l.context)
2247  let l = g:Xgetlist({'nr' : 2, 'context' : 1})
2248  call assert_equal([2], l.context)
2249  let l = g:Xgetlist({'nr' : 3, 'context' : 1})
2250  call assert_equal([3], l.context)
2251
2252  " Test for changing the context through reference and for garbage
2253  " collection of quickfix context
2254  let l = ["red"]
2255  call g:Xsetlist([], ' ', {'context' : l})
2256  call add(l, "blue")
2257  let x = g:Xgetlist({'context' : 1})
2258  call add(x.context, "green")
2259  call assert_equal(["red", "blue", "green"], l)
2260  call assert_equal(["red", "blue", "green"], x.context)
2261  unlet l
2262  call test_garbagecollect_now()
2263  let m = g:Xgetlist({'context' : 1})
2264  call assert_equal(["red", "blue", "green"], m.context)
2265
2266  " Test for setting/getting items
2267  Xexpr ""
2268  let qfprev = g:Xgetlist({'nr':0})
2269  let s = g:Xsetlist([], ' ', {'title':'Green',
2270        \ 'items' : [{'filename':'F1', 'lnum':10}]})
2271  call assert_equal(0, s)
2272  let qfcur = g:Xgetlist({'nr':0})
2273  call assert_true(qfcur.nr == qfprev.nr + 1)
2274  let l = g:Xgetlist({'items':1})
2275  call assert_equal('F1', bufname(l.items[0].bufnr))
2276  call assert_equal(10, l.items[0].lnum)
2277  call g:Xsetlist([], 'a', {'items' : [{'filename':'F2', 'lnum':20},
2278        \  {'filename':'F2', 'lnum':30}]})
2279  let l = g:Xgetlist({'items':1})
2280  call assert_equal('F2', bufname(l.items[2].bufnr))
2281  call assert_equal(30, l.items[2].lnum)
2282  call g:Xsetlist([], 'r', {'items' : [{'filename':'F3', 'lnum':40}]})
2283  let l = g:Xgetlist({'items':1})
2284  call assert_equal('F3', bufname(l.items[0].bufnr))
2285  call assert_equal(40, l.items[0].lnum)
2286  call g:Xsetlist([], 'r', {'items' : []})
2287  let l = g:Xgetlist({'items':1})
2288  call assert_equal(0, len(l.items))
2289
2290  call g:Xsetlist([], 'r', {'title' : 'TestTitle'})
2291  call g:Xsetlist([], 'r', {'items' : [{'filename' : 'F1', 'lnum' : 10, 'text' : 'L10'}]})
2292  call g:Xsetlist([], 'r', {'items' : [{'filename' : 'F1', 'lnum' : 10, 'text' : 'L10'}]})
2293  call assert_equal('TestTitle', g:Xgetlist({'title' : 1}).title)
2294
2295  " Test for getting id of window associated with a location list window
2296  if a:cchar == 'l'
2297    only
2298    call assert_equal(0, g:Xgetlist({'all' : 1}).filewinid)
2299    let wid = win_getid()
2300    Xopen
2301    call assert_equal(wid, g:Xgetlist({'filewinid' : 1}).filewinid)
2302    wincmd w
2303    call assert_equal(0, g:Xgetlist({'filewinid' : 1}).filewinid)
2304    only
2305  endif
2306
2307  " The following used to crash Vim with address sanitizer
2308  call g:Xsetlist([], 'f')
2309  call g:Xsetlist([], 'a', {'items' : [{'filename':'F1', 'lnum':10}]})
2310  call assert_equal(10, g:Xgetlist({'items':1}).items[0].lnum)
2311
2312  " Try setting the items using a string
2313  call assert_equal(-1, g:Xsetlist([], ' ', {'items' : 'Test'}))
2314
2315  " Save and restore the quickfix stack
2316  call g:Xsetlist([], 'f')
2317  call assert_equal(0, g:Xgetlist({'nr':'$'}).nr)
2318  Xexpr "File1:10:Line1"
2319  Xexpr "File2:20:Line2"
2320  Xexpr "File3:30:Line3"
2321  let last_qf = g:Xgetlist({'nr':'$'}).nr
2322  call assert_equal(3, last_qf)
2323  let qstack = []
2324  for i in range(1, last_qf)
2325    let qstack = add(qstack, g:Xgetlist({'nr':i, 'all':1}))
2326  endfor
2327  call g:Xsetlist([], 'f')
2328  for i in range(len(qstack))
2329    call g:Xsetlist([], ' ', qstack[i])
2330  endfor
2331  call assert_equal(3, g:Xgetlist({'nr':'$'}).nr)
2332  call assert_equal(10, g:Xgetlist({'nr':1, 'items':1}).items[0].lnum)
2333  call assert_equal(20, g:Xgetlist({'nr':2, 'items':1}).items[0].lnum)
2334  call assert_equal(30, g:Xgetlist({'nr':3, 'items':1}).items[0].lnum)
2335  call g:Xsetlist([], 'f')
2336
2337  " Swap two quickfix lists
2338  Xexpr "File1:10:Line10"
2339  Xexpr "File2:20:Line20"
2340  Xexpr "File3:30:Line30"
2341  call g:Xsetlist([], 'r', {'nr':1,'title':'Colors','context':['Colors']})
2342  call g:Xsetlist([], 'r', {'nr':2,'title':'Fruits','context':['Fruits']})
2343  let l1=g:Xgetlist({'nr':1,'all':1})
2344  let l2=g:Xgetlist({'nr':2,'all':1})
2345  let save_id = l1.id
2346  let l1.id=l2.id
2347  let l2.id=save_id
2348  call g:Xsetlist([], 'r', l1)
2349  call g:Xsetlist([], 'r', l2)
2350  let newl1=g:Xgetlist({'nr':1,'all':1})
2351  let newl2=g:Xgetlist({'nr':2,'all':1})
2352  call assert_equal('Fruits', newl1.title)
2353  call assert_equal(['Fruits'], newl1.context)
2354  call assert_equal('Line20', newl1.items[0].text)
2355  call assert_equal('Colors', newl2.title)
2356  call assert_equal(['Colors'], newl2.context)
2357  call assert_equal('Line10', newl2.items[0].text)
2358  call g:Xsetlist([], 'f')
2359
2360  " Cannot specify both a non-empty list argument and a dict argument
2361  call assert_fails("call g:Xsetlist([{}], ' ', {})", 'E475:')
2362endfunc
2363
2364func Test_qf_property()
2365  call Xproperty_tests('c')
2366  call Xproperty_tests('l')
2367endfunc
2368
2369" Test for setting the current index in the location/quickfix list
2370func Xtest_setqfidx(cchar)
2371  call s:setup_commands(a:cchar)
2372
2373  Xgetexpr "F1:10:1:Line1\nF2:20:2:Line2\nF3:30:3:Line3"
2374  Xgetexpr "F4:10:1:Line1\nF5:20:2:Line2\nF6:30:3:Line3"
2375  Xgetexpr "F7:10:1:Line1\nF8:20:2:Line2\nF9:30:3:Line3"
2376
2377  call g:Xsetlist([], 'a', {'nr' : 3, 'idx' : 2})
2378  call g:Xsetlist([], 'a', {'nr' : 2, 'idx' : 2})
2379  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 3})
2380  Xolder 2
2381  Xopen
2382  call assert_equal(3, line('.'))
2383  Xnewer
2384  call assert_equal(2, line('.'))
2385  Xnewer
2386  call assert_equal(2, line('.'))
2387  " Update the current index with the quickfix window open
2388  wincmd w
2389  call g:Xsetlist([], 'a', {'nr' : 3, 'idx' : 3})
2390  Xopen
2391  call assert_equal(3, line('.'))
2392  Xclose
2393
2394  " Set the current index to the last entry
2395  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : '$'})
2396  call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx)
2397  " A large value should set the index to the last index
2398  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 1})
2399  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 999})
2400  call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx)
2401  " Invalid index values
2402  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : -1})
2403  call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx)
2404  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 0})
2405  call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx)
2406  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 'xx'})
2407  call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx)
2408  call assert_fails("call g:Xsetlist([], 'a', {'nr':1, 'idx':[]})", 'E745:')
2409
2410  call g:Xsetlist([], 'f')
2411  new | only
2412endfunc
2413
2414func Test_setqfidx()
2415  call Xtest_setqfidx('c')
2416  call Xtest_setqfidx('l')
2417endfunc
2418
2419" Tests for the QuickFixCmdPre/QuickFixCmdPost autocommands
2420func QfAutoCmdHandler(loc, cmd)
2421  call add(g:acmds, a:loc . a:cmd)
2422endfunc
2423
2424func Test_Autocmd()
2425  autocmd QuickFixCmdPre * call QfAutoCmdHandler('pre', expand('<amatch>'))
2426  autocmd QuickFixCmdPost * call QfAutoCmdHandler('post', expand('<amatch>'))
2427
2428  let g:acmds = []
2429  cexpr "F1:10:Line 10"
2430  caddexpr "F1:20:Line 20"
2431  cgetexpr "F1:30:Line 30"
2432  cexpr ""
2433  caddexpr ""
2434  cgetexpr ""
2435  silent! cexpr non_existing_func()
2436  silent! caddexpr non_existing_func()
2437  silent! cgetexpr non_existing_func()
2438  let l = ['precexpr',
2439	      \ 'postcexpr',
2440	      \ 'precaddexpr',
2441	      \ 'postcaddexpr',
2442	      \ 'precgetexpr',
2443	      \ 'postcgetexpr',
2444	      \ 'precexpr',
2445	      \ 'postcexpr',
2446	      \ 'precaddexpr',
2447	      \ 'postcaddexpr',
2448	      \ 'precgetexpr',
2449	      \ 'postcgetexpr',
2450	      \ 'precexpr',
2451	      \ 'precaddexpr',
2452	      \ 'precgetexpr']
2453  call assert_equal(l, g:acmds)
2454
2455  let g:acmds = []
2456  enew! | call append(0, "F2:10:Line 10")
2457  cbuffer!
2458  enew! | call append(0, "F2:20:Line 20")
2459  cgetbuffer
2460  enew! | call append(0, "F2:30:Line 30")
2461  caddbuffer
2462  new
2463  let bnum = bufnr('%')
2464  bunload
2465  exe 'silent! cbuffer! ' . bnum
2466  exe 'silent! cgetbuffer ' . bnum
2467  exe 'silent! caddbuffer ' . bnum
2468  enew!
2469  let l = ['precbuffer',
2470	      \ 'postcbuffer',
2471	      \ 'precgetbuffer',
2472	      \ 'postcgetbuffer',
2473	      \ 'precaddbuffer',
2474	      \ 'postcaddbuffer',
2475	      \ 'precbuffer',
2476	      \ 'precgetbuffer',
2477	      \ 'precaddbuffer']
2478  call assert_equal(l, g:acmds)
2479
2480  call writefile(['Xtest:1:Line1'], 'Xtest')
2481  call writefile([], 'Xempty')
2482  let g:acmds = []
2483  cfile Xtest
2484  caddfile Xtest
2485  cgetfile Xtest
2486  cfile Xempty
2487  caddfile Xempty
2488  cgetfile Xempty
2489  silent! cfile do_not_exist
2490  silent! caddfile do_not_exist
2491  silent! cgetfile do_not_exist
2492  let l = ['precfile',
2493	      \ 'postcfile',
2494	      \ 'precaddfile',
2495	      \ 'postcaddfile',
2496	      \ 'precgetfile',
2497	      \ 'postcgetfile',
2498	      \ 'precfile',
2499	      \ 'postcfile',
2500	      \ 'precaddfile',
2501	      \ 'postcaddfile',
2502	      \ 'precgetfile',
2503	      \ 'postcgetfile',
2504	      \ 'precfile',
2505	      \ 'postcfile',
2506	      \ 'precaddfile',
2507	      \ 'postcaddfile',
2508	      \ 'precgetfile',
2509	      \ 'postcgetfile']
2510  call assert_equal(l, g:acmds)
2511
2512  let g:acmds = []
2513  helpgrep quickfix
2514  silent! helpgrep non_existing_help_topic
2515  vimgrep test Xtest
2516  vimgrepadd test Xtest
2517  silent! vimgrep non_existing_test Xtest
2518  silent! vimgrepadd non_existing_test Xtest
2519  set makeprg=
2520  silent! make
2521  set makeprg&
2522  let l = ['prehelpgrep',
2523	      \ 'posthelpgrep',
2524	      \ 'prehelpgrep',
2525	      \ 'posthelpgrep',
2526	      \ 'previmgrep',
2527	      \ 'postvimgrep',
2528	      \ 'previmgrepadd',
2529	      \ 'postvimgrepadd',
2530	      \ 'previmgrep',
2531	      \ 'postvimgrep',
2532	      \ 'previmgrepadd',
2533	      \ 'postvimgrepadd',
2534	      \ 'premake',
2535	      \ 'postmake']
2536  call assert_equal(l, g:acmds)
2537
2538  if has('unix')
2539    " Run this test only on Unix-like systems. The grepprg may not be set on
2540    " non-Unix systems.
2541    " The following lines are used for the grep test. Don't remove.
2542    " Grep_Autocmd_Text: Match 1
2543    " GrepAdd_Autocmd_Text: Match 2
2544    let g:acmds = []
2545    silent grep Grep_Autocmd_Text test_quickfix.vim
2546    silent grepadd GrepAdd_Autocmd_Text test_quickfix.vim
2547    silent grep abc123def Xtest
2548    silent grepadd abc123def Xtest
2549    set grepprg=internal
2550    silent grep Grep_Autocmd_Text test_quickfix.vim
2551    silent grepadd GrepAdd_Autocmd_Text test_quickfix.vim
2552    silent lgrep Grep_Autocmd_Text test_quickfix.vim
2553    silent lgrepadd GrepAdd_Autocmd_Text test_quickfix.vim
2554    set grepprg&vim
2555    let l = ['pregrep',
2556		\ 'postgrep',
2557		\ 'pregrepadd',
2558		\ 'postgrepadd',
2559		\ 'pregrep',
2560		\ 'postgrep',
2561		\ 'pregrepadd',
2562		\ 'postgrepadd',
2563		\ 'pregrep',
2564		\ 'postgrep',
2565		\ 'pregrepadd',
2566		\ 'postgrepadd',
2567		\ 'prelgrep',
2568		\ 'postlgrep',
2569		\ 'prelgrepadd',
2570		\ 'postlgrepadd']
2571    call assert_equal(l, g:acmds)
2572  endif
2573
2574  call delete('Xtest')
2575  call delete('Xempty')
2576  au! QuickFixCmdPre
2577  au! QuickFixCmdPost
2578endfunc
2579
2580func Test_Autocmd_Exception()
2581  set efm=%m
2582  lgetexpr '?'
2583
2584  try
2585    call DoesNotExit()
2586  catch
2587    lgetexpr '1'
2588  finally
2589    lgetexpr '1'
2590  endtry
2591
2592  call assert_equal('1', getloclist(0)[0].text)
2593
2594  set efm&vim
2595endfunc
2596
2597func Test_caddbuffer_wrong()
2598  " This used to cause a memory access in freed memory.
2599  let save_efm = &efm
2600  set efm=%EEEE%m,%WWWW,%+CCCC%>%#,%GGGG%.#
2601  cgetexpr ['WWWW', 'EEEE', 'CCCC']
2602  let &efm = save_efm
2603  caddbuffer
2604  bwipe!
2605endfunc
2606
2607func Test_caddexpr_wrong()
2608  " This used to cause a memory access in freed memory.
2609  cbuffer
2610  cbuffer
2611  copen
2612  let save_efm = &efm
2613  set efm=%
2614  call assert_fails('caddexpr ""', 'E376:')
2615  let &efm = save_efm
2616endfunc
2617
2618func Test_dirstack_cleanup()
2619  " This used to cause a memory access in freed memory.
2620  let save_efm = &efm
2621  lexpr '0'
2622  lopen
2623  fun X(c)
2624    let save_efm=&efm
2625    set efm=%D%f
2626    if a:c == 'c'
2627      caddexpr '::'
2628    else
2629      laddexpr ':0:0'
2630    endif
2631    let &efm=save_efm
2632  endfun
2633  call X('c')
2634  call X('l')
2635  call setqflist([], 'r')
2636  caddbuffer
2637  let &efm = save_efm
2638endfunc
2639
2640" Tests for jumping to entries from the location list window and quickfix
2641" window
2642func Test_cwindow_jump()
2643  set efm=%f%%%l%%%m
2644  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2645  lopen | only
2646  lfirst
2647  call assert_true(winnr('$') == 2)
2648  call assert_true(winnr() == 1)
2649  " Location list for the new window should be set
2650  call assert_true(getloclist(0)[2].text == 'Line 30')
2651
2652  " Open a scratch buffer
2653  " Open a new window and create a location list
2654  " Open the location list window and close the other window
2655  " Jump to an entry.
2656  " Should create a new window and jump to the entry. The scratch buffer
2657  " should not be used.
2658  enew | only
2659  set buftype=nofile
2660  below new
2661  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2662  lopen
2663  2wincmd c
2664  lnext
2665  call assert_true(winnr('$') == 3)
2666  call assert_true(winnr() == 2)
2667
2668  " Open two windows with two different location lists
2669  " Open the location list window and close the previous window
2670  " Jump to an entry in the location list window
2671  " Should open the file in the first window and not set the location list.
2672  enew | only
2673  lgetexpr ["F1%5%Line 5"]
2674  below new
2675  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2676  lopen
2677  2wincmd c
2678  lnext
2679  call assert_true(winnr() == 1)
2680  call assert_true(getloclist(0)[0].text == 'Line 5')
2681
2682  enew | only
2683  cgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2684  copen
2685  cnext
2686  call assert_true(winnr('$') == 2)
2687  call assert_true(winnr() == 1)
2688
2689  " open the quickfix buffer in two windows and jump to an entry. Should open
2690  " the file in the first quickfix window.
2691  enew | only
2692  copen
2693  let bnum = bufnr('')
2694  exe 'sbuffer ' . bnum
2695  wincmd b
2696  cfirst
2697  call assert_equal(2, winnr())
2698  call assert_equal('F1', @%)
2699  enew | only
2700  exe 'sb' bnum
2701  exe 'botright sb' bnum
2702  wincmd t
2703  clast
2704  call assert_equal(2, winnr())
2705  call assert_equal('quickfix', getwinvar(1, '&buftype'))
2706  call assert_equal('quickfix', getwinvar(3, '&buftype'))
2707
2708  " Jumping to a file from the location list window should find a usable
2709  " window by wrapping around the window list.
2710  enew | only
2711  call setloclist(0, [], 'f')
2712  new | new
2713  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2714  lopen
2715  1close
2716  call assert_equal(0, getloclist(3, {'id' : 0}).id)
2717  lnext
2718  call assert_equal(3, winnr())
2719  call assert_equal(getloclist(1, {'id' : 0}).id, getloclist(3, {'id' : 0}).id)
2720
2721  enew | only
2722  set efm&vim
2723endfunc
2724
2725func Test_cwindow_highlight()
2726  CheckScreendump
2727
2728  let lines =<< trim END
2729	call setline(1, ['some', 'text', 'with', 'matches'])
2730	write XCwindow
2731	vimgrep e XCwindow
2732	redraw
2733	cwindow 4
2734  END
2735  call writefile(lines, 'XtestCwindow')
2736  let buf = RunVimInTerminal('-S XtestCwindow', #{rows: 12})
2737  call VerifyScreenDump(buf, 'Test_quickfix_cwindow_1', {})
2738
2739  call term_sendkeys(buf, ":cnext\<CR>")
2740  call VerifyScreenDump(buf, 'Test_quickfix_cwindow_2', {})
2741
2742  " clean up
2743  call StopVimInTerminal(buf)
2744  call delete('XtestCwindow')
2745  call delete('XCwindow')
2746endfunc
2747
2748func XvimgrepTests(cchar)
2749  call s:setup_commands(a:cchar)
2750
2751  call writefile(['Editor:VIM vim',
2752	      \ 'Editor:Emacs EmAcS',
2753	      \ 'Editor:Notepad NOTEPAD'], 'Xtestfile1')
2754  call writefile(['Linux', 'MacOS', 'MS-Windows'], 'Xtestfile2')
2755
2756  " Error cases
2757  call assert_fails('Xvimgrep /abc *', 'E682:')
2758
2759  let @/=''
2760  call assert_fails('Xvimgrep // *', 'E35:')
2761
2762  call assert_fails('Xvimgrep abc', 'E683:')
2763  call assert_fails('Xvimgrep a1b2c3 Xtestfile1', 'E480:')
2764  call assert_fails('Xvimgrep pat Xa1b2c3', 'E480:')
2765
2766  Xexpr ""
2767  Xvimgrepadd Notepad Xtestfile1
2768  Xvimgrepadd MacOS Xtestfile2
2769  let l = g:Xgetlist()
2770  call assert_equal(2, len(l))
2771  call assert_equal('Editor:Notepad NOTEPAD', l[0].text)
2772
2773  10Xvimgrep #\cvim#g Xtestfile?
2774  let l = g:Xgetlist()
2775  call assert_equal(2, len(l))
2776  call assert_equal(8, l[0].col)
2777  call assert_equal(12, l[1].col)
2778
2779  1Xvimgrep ?Editor? Xtestfile*
2780  let l = g:Xgetlist()
2781  call assert_equal(1, len(l))
2782  call assert_equal('Editor:VIM vim', l[0].text)
2783
2784  edit +3 Xtestfile2
2785  Xvimgrep +\cemacs+j Xtestfile1
2786  let l = g:Xgetlist()
2787  call assert_equal('Xtestfile2', @%)
2788  call assert_equal('Editor:Emacs EmAcS', l[0].text)
2789
2790  " Test for unloading a buffer after vimgrep searched the buffer
2791  %bwipe
2792  Xvimgrep /Editor/j Xtestfile*
2793  call assert_equal(0, getbufinfo('Xtestfile1')[0].loaded)
2794  call assert_equal([], getbufinfo('Xtestfile2'))
2795
2796  call delete('Xtestfile1')
2797  call delete('Xtestfile2')
2798endfunc
2799
2800" Tests for the :vimgrep command
2801func Test_vimgrep()
2802  call XvimgrepTests('c')
2803  call XvimgrepTests('l')
2804endfunc
2805
2806" Test for incsearch highlighting of the :vimgrep pattern
2807" This test used to cause "E315: ml_get: invalid lnum" errors.
2808func Test_vimgrep_incsearch()
2809  enew
2810  set incsearch
2811  call test_override("char_avail", 1)
2812
2813  call feedkeys(":2vimgrep assert test_quickfix.vim test_cdo.vim\<CR>", "ntx")
2814  let l = getqflist()
2815  call assert_equal(2, len(l))
2816
2817  call test_override("ALL", 0)
2818  set noincsearch
2819endfunc
2820
2821" Test vimgrep with the last search pattern not set
2822func Test_vimgrep_with_no_last_search_pat()
2823  let lines =<< trim [SCRIPT]
2824    call assert_fails('vimgrep // *', 'E35:')
2825    call writefile(v:errors, 'Xresult')
2826    qall!
2827  [SCRIPT]
2828  call writefile(lines, 'Xscript')
2829  if RunVim([], [], '--clean -S Xscript')
2830    call assert_equal([], readfile('Xresult'))
2831  endif
2832  call delete('Xscript')
2833  call delete('Xresult')
2834endfunc
2835
2836" Test vimgrep without swap file
2837func Test_vimgrep_without_swap_file()
2838  let lines =<< trim [SCRIPT]
2839    vimgrep grep test_c*
2840    call writefile(['done'], 'Xresult')
2841    qall!
2842  [SCRIPT]
2843  call writefile(lines, 'Xscript')
2844  if RunVim([], [], '--clean -n -S Xscript Xscript')
2845    call assert_equal(['done'], readfile('Xresult'))
2846  endif
2847  call delete('Xscript')
2848  call delete('Xresult')
2849endfunc
2850
2851func Test_vimgrep_existing_swapfile()
2852  call writefile(['match apple with apple'], 'Xapple')
2853  call writefile(['swapfile'], '.Xapple.swp')
2854  let g:foundSwap = 0
2855  let g:ignoreSwapExists = 1
2856  augroup grep
2857    au SwapExists * let foundSwap = 1 | let v:swapchoice = 'e'
2858  augroup END
2859  vimgrep apple Xapple
2860  call assert_equal(1, g:foundSwap)
2861  call assert_match('.Xapple.swo', swapname(''))
2862
2863  call delete('Xapple')
2864  call delete('.Xapple.swp')
2865  augroup grep
2866    au! SwapExists
2867  augroup END
2868  unlet g:ignoreSwapExists
2869endfunc
2870
2871func XfreeTests(cchar)
2872  call s:setup_commands(a:cchar)
2873
2874  enew | only
2875
2876  " Deleting the quickfix stack should work even When the current list is
2877  " somewhere in the middle of the stack
2878  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2879  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2880  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2881  Xolder
2882  call g:Xsetlist([], 'f')
2883  call assert_equal(0, len(g:Xgetlist()))
2884
2885  " After deleting the stack, adding a new list should create a stack with a
2886  " single list.
2887  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2888  call assert_equal(1, g:Xgetlist({'all':1}).nr)
2889
2890  " Deleting the stack from a quickfix window should update/clear the
2891  " quickfix/location list window.
2892  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2893  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2894  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2895  Xolder
2896  Xwindow
2897  call g:Xsetlist([], 'f')
2898  call assert_equal(2, winnr('$'))
2899  call assert_equal(1, line('$'))
2900  Xclose
2901
2902  " Deleting the stack from a non-quickfix window should update/clear the
2903  " quickfix/location list window.
2904  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2905  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2906  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2907  Xolder
2908  Xwindow
2909  wincmd p
2910  call g:Xsetlist([], 'f')
2911  call assert_equal(0, len(g:Xgetlist()))
2912  wincmd p
2913  call assert_equal(2, winnr('$'))
2914  call assert_equal(1, line('$'))
2915
2916  " After deleting the location list stack, if the location list window is
2917  " opened, then a new location list should be created. So opening the
2918  " location list window again should not create a new window.
2919  if a:cchar == 'l'
2920      lexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2921      wincmd p
2922      lopen
2923      call assert_equal(2, winnr('$'))
2924  endif
2925  Xclose
2926endfunc
2927
2928" Tests for the quickfix free functionality
2929func Test_qf_free()
2930  call XfreeTests('c')
2931  call XfreeTests('l')
2932endfunc
2933
2934" Test for buffer overflow when parsing lines and adding new entries to
2935" the quickfix list.
2936func Test_bufoverflow()
2937  set efm=%f:%l:%m
2938  cgetexpr ['File1:100:' . repeat('x', 1025)]
2939
2940  set efm=%+GCompiler:\ %.%#,%f:%l:%m
2941  cgetexpr ['Compiler: ' . repeat('a', 1015), 'File1:10:Hello World']
2942
2943  set efm=%DEntering\ directory\ %f,%f:%l:%m
2944  cgetexpr ['Entering directory ' . repeat('a', 1006),
2945	      \ 'File1:10:Hello World']
2946  set efm&vim
2947endfunc
2948
2949" Tests for getting the quickfix stack size
2950func XsizeTests(cchar)
2951  call s:setup_commands(a:cchar)
2952
2953  call g:Xsetlist([], 'f')
2954  call assert_equal(0, g:Xgetlist({'nr':'$'}).nr)
2955  call assert_equal('', g:Xgetlist({'nr':'$', 'all':1}).title)
2956  call assert_equal(0, g:Xgetlist({'nr':0}).nr)
2957
2958  Xexpr "File1:10:Line1"
2959  Xexpr "File2:20:Line2"
2960  Xexpr "File3:30:Line3"
2961  Xolder | Xolder
2962  call assert_equal(3, g:Xgetlist({'nr':'$'}).nr)
2963  call g:Xsetlist([], 'f')
2964
2965  Xexpr "File1:10:Line1"
2966  Xexpr "File2:20:Line2"
2967  Xexpr "File3:30:Line3"
2968  Xolder | Xolder
2969  call g:Xsetlist([], 'a', {'nr':'$', 'title':'Compiler'})
2970  call assert_equal('Compiler', g:Xgetlist({'nr':3, 'all':1}).title)
2971endfunc
2972
2973func Test_Qf_Size()
2974  call XsizeTests('c')
2975  call XsizeTests('l')
2976endfunc
2977
2978func Test_cclose_from_copen()
2979    augroup QF_Test
2980	au!
2981        au FileType qf :call assert_fails(':cclose', 'E788:')
2982    augroup END
2983    copen
2984    augroup QF_Test
2985	au!
2986    augroup END
2987    augroup! QF_Test
2988endfunc
2989
2990func Test_cclose_in_autocmd()
2991  " Problem is only triggered if "starting" is zero, so that the OptionsSet
2992  " event will be triggered.
2993  call test_override('starting', 1)
2994  augroup QF_Test
2995    au!
2996    au FileType qf :call assert_fails(':cclose', 'E788:')
2997  augroup END
2998  copen
2999  augroup QF_Test
3000    au!
3001  augroup END
3002  augroup! QF_Test
3003  call test_override('starting', 0)
3004endfunc
3005
3006" Check that ":file" without an argument is possible even when "curbuf_lock"
3007" is set.
3008func Test_file_from_copen()
3009  " Works without argument.
3010  augroup QF_Test
3011    au!
3012    au FileType qf file
3013  augroup END
3014  copen
3015
3016  augroup QF_Test
3017    au!
3018  augroup END
3019  cclose
3020
3021  " Fails with argument.
3022  augroup QF_Test
3023    au!
3024    au FileType qf call assert_fails(':file foo', 'E788:')
3025  augroup END
3026  copen
3027  augroup QF_Test
3028    au!
3029  augroup END
3030  cclose
3031
3032  augroup! QF_Test
3033endfunc
3034
3035func Test_resize_from_copen()
3036  augroup QF_Test
3037    au!
3038    au FileType qf resize 5
3039  augroup END
3040  try
3041    " This should succeed without any exception.  No other buffers are
3042    " involved in the autocmd.
3043    copen
3044  finally
3045    augroup QF_Test
3046      au!
3047    augroup END
3048    augroup! QF_Test
3049  endtry
3050endfunc
3051
3052" Tests for the quickfix buffer b:changedtick variable
3053func Xchangedtick_tests(cchar)
3054  call s:setup_commands(a:cchar)
3055
3056  new | only
3057
3058  Xexpr "" | Xexpr "" | Xexpr ""
3059
3060  Xopen
3061  Xolder
3062  Xolder
3063  Xaddexpr "F1:10:Line10"
3064  Xaddexpr "F2:20:Line20"
3065  call g:Xsetlist([{"filename":"F3", "lnum":30, "text":"Line30"}], 'a')
3066  call g:Xsetlist([], 'f')
3067  call assert_equal(8, getbufvar('%', 'changedtick'))
3068  Xclose
3069endfunc
3070
3071func Test_changedtick()
3072  call Xchangedtick_tests('c')
3073  call Xchangedtick_tests('l')
3074endfunc
3075
3076" Tests for parsing an expression using setqflist()
3077func Xsetexpr_tests(cchar)
3078  call s:setup_commands(a:cchar)
3079
3080  let t = ["File1:10:Line10", "File1:20:Line20"]
3081  call g:Xsetlist([], ' ', {'lines' : t})
3082  call g:Xsetlist([], 'a', {'lines' : ["File1:30:Line30"]})
3083
3084  let l = g:Xgetlist()
3085  call assert_equal(3, len(l))
3086  call assert_equal(20, l[1].lnum)
3087  call assert_equal('Line30', l[2].text)
3088  call g:Xsetlist([], 'r', {'lines' : ["File2:5:Line5"]})
3089  let l = g:Xgetlist()
3090  call assert_equal(1, len(l))
3091  call assert_equal('Line5', l[0].text)
3092  call assert_equal(-1, g:Xsetlist([], 'a', {'lines' : 10}))
3093  call assert_equal(-1, g:Xsetlist([], 'a', {'lines' : "F1:10:L10"}))
3094
3095  call g:Xsetlist([], 'f')
3096  " Add entries to multiple lists
3097  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["File1:10:Line10"]})
3098  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["File2:20:Line20"]})
3099  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["File1:15:Line15"]})
3100  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["File2:25:Line25"]})
3101  call assert_equal('Line15', g:Xgetlist({'nr':1, 'items':1}).items[1].text)
3102  call assert_equal('Line25', g:Xgetlist({'nr':2, 'items':1}).items[1].text)
3103
3104  " Adding entries using a custom efm
3105  set efm&
3106  call g:Xsetlist([], ' ', {'efm' : '%f#%l#%m',
3107				\ 'lines' : ["F1#10#L10", "F2#20#L20"]})
3108  call assert_equal(20, g:Xgetlist({'items':1}).items[1].lnum)
3109  call g:Xsetlist([], 'a', {'efm' : '%f#%l#%m', 'lines' : ["F3:30:L30"]})
3110  call assert_equal('F3:30:L30', g:Xgetlist({'items':1}).items[2].text)
3111  call assert_equal(20, g:Xgetlist({'items':1}).items[1].lnum)
3112  call assert_equal(-1, g:Xsetlist([], 'a', {'efm' : [],
3113				\ 'lines' : ['F1:10:L10']}))
3114endfunc
3115
3116func Test_setexpr()
3117  call Xsetexpr_tests('c')
3118  call Xsetexpr_tests('l')
3119endfunc
3120
3121" Tests for per quickfix/location list directory stack
3122func Xmultidirstack_tests(cchar)
3123  call s:setup_commands(a:cchar)
3124
3125  call g:Xsetlist([], 'f')
3126  Xexpr "" | Xexpr ""
3127
3128  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["Entering dir 'Xone/a'"]})
3129  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["Entering dir 'Xtwo/a'"]})
3130  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["one.txt:3:one one one"]})
3131  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["two.txt:5:two two two"]})
3132
3133  let l1 = g:Xgetlist({'nr':1, 'items':1})
3134  let l2 = g:Xgetlist({'nr':2, 'items':1})
3135  call assert_equal('Xone/a/one.txt', bufname(l1.items[1].bufnr))
3136  call assert_equal(3, l1.items[1].lnum)
3137  call assert_equal('Xtwo/a/two.txt', bufname(l2.items[1].bufnr))
3138  call assert_equal(5, l2.items[1].lnum)
3139endfunc
3140
3141func Test_multidirstack()
3142  call mkdir('Xone/a', 'p')
3143  call mkdir('Xtwo/a', 'p')
3144  let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7']
3145  call writefile(lines, 'Xone/a/one.txt')
3146  call writefile(lines, 'Xtwo/a/two.txt')
3147  let save_efm = &efm
3148  set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f'
3149
3150  call Xmultidirstack_tests('c')
3151  call Xmultidirstack_tests('l')
3152
3153  let &efm = save_efm
3154  call delete('Xone', 'rf')
3155  call delete('Xtwo', 'rf')
3156endfunc
3157
3158" Tests for per quickfix/location list file stack
3159func Xmultifilestack_tests(cchar)
3160  call s:setup_commands(a:cchar)
3161
3162  call g:Xsetlist([], 'f')
3163  Xexpr "" | Xexpr ""
3164
3165  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["[one.txt]"]})
3166  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["[two.txt]"]})
3167  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["(3,5) one one one"]})
3168  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["(5,9) two two two"]})
3169
3170  let l1 = g:Xgetlist({'nr':1, 'items':1})
3171  let l2 = g:Xgetlist({'nr':2, 'items':1})
3172  call assert_equal('one.txt', bufname(l1.items[1].bufnr))
3173  call assert_equal(3, l1.items[1].lnum)
3174  call assert_equal('two.txt', bufname(l2.items[1].bufnr))
3175  call assert_equal(5, l2.items[1].lnum)
3176
3177  " Test for start of a new error line in the same line where a previous
3178  " error line ends with a file stack.
3179  let efm_val = 'Error\ l%l\ in\ %f,'
3180  let efm_val .= '%-P%>(%f%r,Error\ l%l\ in\ %m,%-Q)%r'
3181  let l = g:Xgetlist({'lines' : [
3182	      \ '(one.txt',
3183	      \ 'Error l4 in one.txt',
3184	      \ ') (two.txt',
3185	      \ 'Error l6 in two.txt',
3186	      \ ')',
3187	      \ 'Error l8 in one.txt'
3188	      \ ], 'efm' : efm_val})
3189  call assert_equal(3, len(l.items))
3190  call assert_equal('one.txt', bufname(l.items[0].bufnr))
3191  call assert_equal(4, l.items[0].lnum)
3192  call assert_equal('one.txt', l.items[0].text)
3193  call assert_equal('two.txt', bufname(l.items[1].bufnr))
3194  call assert_equal(6, l.items[1].lnum)
3195  call assert_equal('two.txt', l.items[1].text)
3196  call assert_equal('one.txt', bufname(l.items[2].bufnr))
3197  call assert_equal(8, l.items[2].lnum)
3198  call assert_equal('', l.items[2].text)
3199endfunc
3200
3201func Test_multifilestack()
3202  let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7']
3203  call writefile(lines, 'one.txt')
3204  call writefile(lines, 'two.txt')
3205  let save_efm = &efm
3206  set efm=%+P[%f],(%l\\,%c)\ %m,%-Q
3207
3208  call Xmultifilestack_tests('c')
3209  call Xmultifilestack_tests('l')
3210
3211  let &efm = save_efm
3212  call delete('one.txt')
3213  call delete('two.txt')
3214endfunc
3215
3216" Tests for per buffer 'efm' setting
3217func Test_perbuf_efm()
3218  call writefile(["File1-10-Line10"], 'one.txt')
3219  call writefile(["File2#20#Line20"], 'two.txt')
3220  set efm=%f#%l#%m
3221  new | only
3222  new
3223  setlocal efm=%f-%l-%m
3224  cfile one.txt
3225  wincmd w
3226  caddfile two.txt
3227
3228  let l = getqflist()
3229  call assert_equal(10, l[0].lnum)
3230  call assert_equal('Line20', l[1].text)
3231
3232  set efm&
3233  new | only
3234  call delete('one.txt')
3235  call delete('two.txt')
3236endfunc
3237
3238" Open multiple help windows using ":lhelpgrep
3239" This test used to crash Vim
3240func Test_Multi_LL_Help()
3241  new | only
3242  lhelpgrep window
3243  lopen
3244  e#
3245  lhelpgrep buffer
3246  call assert_equal(3, winnr('$'))
3247  call assert_true(len(getloclist(1)) != 0)
3248  call assert_true(len(getloclist(2)) != 0)
3249  new | only
3250endfunc
3251
3252" Tests for adding new quickfix lists using setqflist()
3253func XaddQf_tests(cchar)
3254  call s:setup_commands(a:cchar)
3255
3256  " Create a new list using ' ' for action
3257  call g:Xsetlist([], 'f')
3258  call g:Xsetlist([], ' ', {'title' : 'Test1'})
3259  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3260  call assert_equal(1, l.nr)
3261  call assert_equal('Test1', l.title)
3262
3263  " Create a new list using ' ' for action and '$' for 'nr'
3264  call g:Xsetlist([], 'f')
3265  call g:Xsetlist([], ' ', {'title' : 'Test2', 'nr' : '$'})
3266  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3267  call assert_equal(1, l.nr)
3268  call assert_equal('Test2', l.title)
3269
3270  " Create a new list using 'a' for action
3271  call g:Xsetlist([], 'f')
3272  call g:Xsetlist([], 'a', {'title' : 'Test3'})
3273  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3274  call assert_equal(1, l.nr)
3275  call assert_equal('Test3', l.title)
3276
3277  " Create a new list using 'a' for action and '$' for 'nr'
3278  call g:Xsetlist([], 'f')
3279  call g:Xsetlist([], 'a', {'title' : 'Test3', 'nr' : '$'})
3280  call g:Xsetlist([], 'a', {'title' : 'Test4'})
3281  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3282  call assert_equal(1, l.nr)
3283  call assert_equal('Test4', l.title)
3284
3285  " Adding a quickfix list should remove all the lists following the current
3286  " list.
3287  Xexpr "" | Xexpr "" | Xexpr ""
3288  silent! 10Xolder
3289  call g:Xsetlist([], ' ', {'title' : 'Test5'})
3290  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3291  call assert_equal(2, l.nr)
3292  call assert_equal('Test5', l.title)
3293
3294  " Add a quickfix list using '$' as the list number.
3295  let lastqf = g:Xgetlist({'nr':'$'}).nr
3296  silent! 99Xolder
3297  call g:Xsetlist([], ' ', {'nr' : '$', 'title' : 'Test6'})
3298  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3299  call assert_equal(lastqf + 1, l.nr)
3300  call assert_equal('Test6', l.title)
3301
3302  " Add a quickfix list using 'nr' set to one more than the quickfix
3303  " list size.
3304  let lastqf = g:Xgetlist({'nr':'$'}).nr
3305  silent! 99Xolder
3306  call g:Xsetlist([], ' ', {'nr' : lastqf + 1, 'title' : 'Test7'})
3307  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3308  call assert_equal(lastqf + 1, l.nr)
3309  call assert_equal('Test7', l.title)
3310
3311  " Add a quickfix list to a stack with 10 lists using 'nr' set to '$'
3312  exe repeat('Xexpr "" |', 9) . 'Xexpr ""'
3313  silent! 99Xolder
3314  call g:Xsetlist([], ' ', {'nr' : '$', 'title' : 'Test8'})
3315  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3316  call assert_equal(10, l.nr)
3317  call assert_equal('Test8', l.title)
3318
3319  " Add a quickfix list using 'nr' set to a value greater than 10
3320  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : 12, 'title' : 'Test9'}))
3321
3322  " Try adding a quickfix list with 'nr' set to a value greater than the
3323  " quickfix list size but less than 10.
3324  call g:Xsetlist([], 'f')
3325  Xexpr "" | Xexpr "" | Xexpr ""
3326  silent! 99Xolder
3327  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : 8, 'title' : 'Test10'}))
3328
3329  " Add a quickfix list using 'nr' set to a some string or list
3330  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : [1,2], 'title' : 'Test11'}))
3331endfunc
3332
3333func Test_add_qf()
3334  call XaddQf_tests('c')
3335  call XaddQf_tests('l')
3336endfunc
3337
3338" Test for getting the quickfix list items from some text without modifying
3339" the quickfix stack
3340func XgetListFromLines(cchar)
3341  call s:setup_commands(a:cchar)
3342  call g:Xsetlist([], 'f')
3343
3344  let l = g:Xgetlist({'lines' : ["File2:20:Line20", "File2:30:Line30"]}).items
3345  call assert_equal(2, len(l))
3346  call assert_equal(30, l[1].lnum)
3347
3348  call assert_equal({}, g:Xgetlist({'lines' : 10}))
3349  call assert_equal({}, g:Xgetlist({'lines' : 'File1:10:Line10'}))
3350  call assert_equal([], g:Xgetlist({'lines' : []}).items)
3351  call assert_equal([], g:Xgetlist({'lines' : [10, 20]}).items)
3352
3353  " Parse text using a custom efm
3354  set efm&
3355  let l = g:Xgetlist({'lines':['File3#30#Line30'], 'efm' : '%f#%l#%m'}).items
3356  call assert_equal('Line30', l[0].text)
3357  let l = g:Xgetlist({'lines':['File3:30:Line30'], 'efm' : '%f-%l-%m'}).items
3358  call assert_equal('File3:30:Line30', l[0].text)
3359  let l = g:Xgetlist({'lines':['File3:30:Line30'], 'efm' : [1,2]})
3360  call assert_equal({}, l)
3361  call assert_fails("call g:Xgetlist({'lines':['abc'], 'efm':'%2'})", 'E376:')
3362  call assert_fails("call g:Xgetlist({'lines':['abc'], 'efm':''})", 'E378:')
3363
3364  " Make sure that the quickfix stack is not modified
3365  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
3366endfunc
3367
3368func Test_get_list_from_lines()
3369  call XgetListFromLines('c')
3370  call XgetListFromLines('l')
3371endfunc
3372
3373" Tests for the quickfix list id
3374func Xqfid_tests(cchar)
3375  call s:setup_commands(a:cchar)
3376
3377  call g:Xsetlist([], 'f')
3378  call assert_equal(0, g:Xgetlist({'id':0}).id)
3379  Xexpr ''
3380  let start_id = g:Xgetlist({'id' : 0}).id
3381  Xexpr '' | Xexpr ''
3382  Xolder
3383  call assert_equal(start_id, g:Xgetlist({'id':0, 'nr':1}).id)
3384  call assert_equal(start_id + 1, g:Xgetlist({'id':0, 'nr':0}).id)
3385  call assert_equal(start_id + 2, g:Xgetlist({'id':0, 'nr':'$'}).id)
3386  call assert_equal(0, g:Xgetlist({'id':0, 'nr':99}).id)
3387  call assert_equal(2, g:Xgetlist({'id':start_id + 1, 'nr':0}).nr)
3388  call assert_equal(0, g:Xgetlist({'id':99, 'nr':0}).id)
3389  call assert_equal(0, g:Xgetlist({'id':"abc", 'nr':0}).id)
3390
3391  call g:Xsetlist([], 'a', {'id':start_id, 'context':[1,2]})
3392  call assert_equal([1,2], g:Xgetlist({'nr':1, 'context':1}).context)
3393  call g:Xsetlist([], 'a', {'id':start_id+1, 'lines':['F1:10:L10']})
3394  call assert_equal('L10', g:Xgetlist({'nr':2, 'items':1}).items[0].text)
3395  call assert_equal(-1, g:Xsetlist([], 'a', {'id':999, 'title':'Vim'}))
3396  call assert_equal(-1, g:Xsetlist([], 'a', {'id':'abc', 'title':'Vim'}))
3397
3398  let qfid = g:Xgetlist({'id':0, 'nr':0})
3399  call g:Xsetlist([], 'f')
3400  call assert_equal(0, g:Xgetlist({'id':qfid, 'nr':0}).id)
3401endfunc
3402
3403func Test_qf_id()
3404  call Xqfid_tests('c')
3405  call Xqfid_tests('l')
3406endfunc
3407
3408func Xqfjump_tests(cchar)
3409  call s:setup_commands(a:cchar)
3410
3411  call writefile(["Line1\tFoo", "Line2"], 'F1')
3412  call writefile(["Line1\tBar", "Line2"], 'F2')
3413  call writefile(["Line1\tBaz", "Line2"], 'F3')
3414
3415  call g:Xsetlist([], 'f')
3416
3417  " Tests for
3418  "   Jumping to a line using a pattern
3419  "   Jumping to a column greater than the last column in a line
3420  "   Jumping to a line greater than the last line in the file
3421  let l = []
3422  for i in range(1, 7)
3423    call add(l, {})
3424  endfor
3425  let l[0].filename='F1'
3426  let l[0].pattern='Line1'
3427  let l[1].filename='F2'
3428  let l[1].pattern='Line1'
3429  let l[2].filename='F3'
3430  let l[2].pattern='Line1'
3431  let l[3].filename='F3'
3432  let l[3].lnum=1
3433  let l[3].col=9
3434  let l[3].vcol=1
3435  let l[4].filename='F3'
3436  let l[4].lnum=99
3437  let l[5].filename='F3'
3438  let l[5].lnum=1
3439  let l[5].col=99
3440  let l[5].vcol=1
3441  let l[6].filename='F3'
3442  let l[6].pattern='abcxyz'
3443
3444  call g:Xsetlist([], ' ', {'items' : l})
3445  Xopen | only
3446  2Xnext
3447  call assert_equal(3, g:Xgetlist({'idx' : 0}).idx)
3448  call assert_equal('F3', @%)
3449  Xnext
3450  call assert_equal(7, col('.'))
3451  Xnext
3452  call assert_equal(2, line('.'))
3453  Xnext
3454  call assert_equal(9, col('.'))
3455  2
3456  Xnext
3457  call assert_equal(2, line('.'))
3458
3459  if a:cchar == 'l'
3460    " When jumping to a location list entry in the location list window and
3461    " no usable windows are available, then a new window should be opened.
3462    enew! | new | only
3463    call g:Xsetlist([], 'f')
3464    setlocal buftype=nofile
3465    new
3466    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']})
3467    Xopen
3468    let winid = win_getid()
3469    wincmd p
3470    close
3471    call win_gotoid(winid)
3472    Xnext
3473    call assert_equal(3, winnr('$'))
3474    call assert_equal(1, winnr())
3475    call assert_equal(2, line('.'))
3476
3477    " When jumping to an entry in the location list window and the window
3478    " associated with the location list is not present and a window containing
3479    " the file is already present, then that window should be used.
3480    close
3481    belowright new
3482    call g:Xsetlist([], 'f')
3483    edit F3
3484    call win_gotoid(winid)
3485    Xlast
3486    call assert_equal(3, winnr())
3487    call assert_equal(6, g:Xgetlist({'size' : 1}).size)
3488    call assert_equal(winid, g:Xgetlist({'winid' : 1}).winid)
3489  endif
3490
3491  " Cleanup
3492  enew!
3493  new | only
3494
3495  call delete('F1')
3496  call delete('F2')
3497  call delete('F3')
3498endfunc
3499
3500func Test_qfjump()
3501  call Xqfjump_tests('c')
3502  call Xqfjump_tests('l')
3503endfunc
3504
3505" Tests for the getqflist() and getloclist() functions when the list is not
3506" present or is empty
3507func Xgetlist_empty_tests(cchar)
3508  call s:setup_commands(a:cchar)
3509
3510  " Empty quickfix stack
3511  call g:Xsetlist([], 'f')
3512  call assert_equal('', g:Xgetlist({'context' : 0}).context)
3513  call assert_equal(0, g:Xgetlist({'id' : 0}).id)
3514  call assert_equal(0, g:Xgetlist({'idx' : 0}).idx)
3515  call assert_equal([], g:Xgetlist({'items' : 0}).items)
3516  call assert_equal(0, g:Xgetlist({'nr' : 0}).nr)
3517  call assert_equal(0, g:Xgetlist({'size' : 0}).size)
3518  call assert_equal('', g:Xgetlist({'title' : 0}).title)
3519  call assert_equal(0, g:Xgetlist({'winid' : 0}).winid)
3520  call assert_equal(0, g:Xgetlist({'changedtick' : 0}).changedtick)
3521  if a:cchar == 'c'
3522    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0,
3523		  \ 'items' : [], 'nr' : 0, 'size' : 0, 'qfbufnr' : 0,
3524		  \ 'title' : '', 'winid' : 0, 'changedtick': 0,
3525                  \ 'quickfixtextfunc' : ''}, g:Xgetlist({'all' : 0}))
3526  else
3527    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0,
3528		\ 'items' : [], 'nr' : 0, 'size' : 0, 'title' : '',
3529		\ 'winid' : 0, 'changedtick': 0, 'filewinid' : 0,
3530		\ 'qfbufnr' : 0, 'quickfixtextfunc' : ''},
3531		\ g:Xgetlist({'all' : 0}))
3532  endif
3533
3534  " Quickfix window with empty stack
3535  silent! Xopen
3536  let qfwinid = (a:cchar == 'c') ? win_getid() : 0
3537  let qfbufnr = (a:cchar == 'c') ? bufnr('') : 0
3538  call assert_equal(qfwinid, g:Xgetlist({'winid' : 0}).winid)
3539  Xclose
3540
3541  " Empty quickfix list
3542  Xexpr ""
3543  call assert_equal('', g:Xgetlist({'context' : 0}).context)
3544  call assert_notequal(0, g:Xgetlist({'id' : 0}).id)
3545  call assert_equal(0, g:Xgetlist({'idx' : 0}).idx)
3546  call assert_equal([], g:Xgetlist({'items' : 0}).items)
3547  call assert_notequal(0, g:Xgetlist({'nr' : 0}).nr)
3548  call assert_equal(0, g:Xgetlist({'size' : 0}).size)
3549  call assert_notequal('', g:Xgetlist({'title' : 0}).title)
3550  call assert_equal(0, g:Xgetlist({'winid' : 0}).winid)
3551  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3552
3553  let qfid = g:Xgetlist({'id' : 0}).id
3554  call g:Xsetlist([], 'f')
3555
3556  " Non-existing quickfix identifier
3557  call assert_equal('', g:Xgetlist({'id' : qfid, 'context' : 0}).context)
3558  call assert_equal(0, g:Xgetlist({'id' : qfid}).id)
3559  call assert_equal(0, g:Xgetlist({'id' : qfid, 'idx' : 0}).idx)
3560  call assert_equal([], g:Xgetlist({'id' : qfid, 'items' : 0}).items)
3561  call assert_equal(0, g:Xgetlist({'id' : qfid, 'nr' : 0}).nr)
3562  call assert_equal(0, g:Xgetlist({'id' : qfid, 'size' : 0}).size)
3563  call assert_equal('', g:Xgetlist({'id' : qfid, 'title' : 0}).title)
3564  call assert_equal(0, g:Xgetlist({'id' : qfid, 'winid' : 0}).winid)
3565  call assert_equal(0, g:Xgetlist({'id' : qfid, 'changedtick' : 0}).changedtick)
3566  if a:cchar == 'c'
3567    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
3568		\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
3569		\ 'qfbufnr' : qfbufnr, 'quickfixtextfunc' : '',
3570		\ 'changedtick' : 0}, g:Xgetlist({'id' : qfid, 'all' : 0}))
3571  else
3572    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
3573		\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
3574		\ 'changedtick' : 0, 'filewinid' : 0, 'qfbufnr' : 0,
3575                \ 'quickfixtextfunc' : ''},
3576		\ g:Xgetlist({'id' : qfid, 'all' : 0}))
3577  endif
3578
3579  " Non-existing quickfix list number
3580  call assert_equal('', g:Xgetlist({'nr' : 5, 'context' : 0}).context)
3581  call assert_equal(0, g:Xgetlist({'nr' : 5}).nr)
3582  call assert_equal(0, g:Xgetlist({'nr' : 5, 'idx' : 0}).idx)
3583  call assert_equal([], g:Xgetlist({'nr' : 5, 'items' : 0}).items)
3584  call assert_equal(0, g:Xgetlist({'nr' : 5, 'id' : 0}).id)
3585  call assert_equal(0, g:Xgetlist({'nr' : 5, 'size' : 0}).size)
3586  call assert_equal('', g:Xgetlist({'nr' : 5, 'title' : 0}).title)
3587  call assert_equal(0, g:Xgetlist({'nr' : 5, 'winid' : 0}).winid)
3588  call assert_equal(0, g:Xgetlist({'nr' : 5, 'changedtick' : 0}).changedtick)
3589  if a:cchar == 'c'
3590    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
3591		\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
3592		\ 'changedtick' : 0, 'qfbufnr' : qfbufnr,
3593                \ 'quickfixtextfunc' : ''}, g:Xgetlist({'nr' : 5, 'all' : 0}))
3594  else
3595    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
3596		\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
3597		\ 'changedtick' : 0, 'filewinid' : 0, 'qfbufnr' : 0,
3598                \ 'quickfixtextfunc' : ''}, g:Xgetlist({'nr' : 5, 'all' : 0}))
3599  endif
3600endfunc
3601
3602func Test_getqflist()
3603  call Xgetlist_empty_tests('c')
3604  call Xgetlist_empty_tests('l')
3605endfunc
3606
3607func Test_getqflist_invalid_nr()
3608  " The following commands used to crash Vim
3609  cexpr ""
3610  call getqflist({'nr' : $XXX_DOES_NOT_EXIST_XXX})
3611
3612  " Cleanup
3613  call setqflist([], 'r')
3614endfunc
3615
3616" Tests for the quickfix/location list changedtick
3617func Xqftick_tests(cchar)
3618  call s:setup_commands(a:cchar)
3619
3620  call g:Xsetlist([], 'f')
3621
3622  Xexpr "F1:10:Line10"
3623  let qfid = g:Xgetlist({'id' : 0}).id
3624  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3625  Xaddexpr "F2:20:Line20\nF2:21:Line21"
3626  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
3627  call g:Xsetlist([], 'a', {'lines' : ["F3:30:Line30", "F3:31:Line31"]})
3628  call assert_equal(3, g:Xgetlist({'changedtick' : 0}).changedtick)
3629  call g:Xsetlist([], 'r', {'lines' : ["F4:40:Line40"]})
3630  call assert_equal(4, g:Xgetlist({'changedtick' : 0}).changedtick)
3631  call g:Xsetlist([], 'a', {'title' : 'New Title'})
3632  call assert_equal(5, g:Xgetlist({'changedtick' : 0}).changedtick)
3633
3634  enew!
3635  call append(0, ["F5:50:L50", "F6:60:L60"])
3636  Xaddbuffer
3637  call assert_equal(6, g:Xgetlist({'changedtick' : 0}).changedtick)
3638  enew!
3639
3640  call g:Xsetlist([], 'a', {'context' : {'bus' : 'pci'}})
3641  call assert_equal(7, g:Xgetlist({'changedtick' : 0}).changedtick)
3642  call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'},
3643	      \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], 'a')
3644  call assert_equal(8, g:Xgetlist({'changedtick' : 0}).changedtick)
3645  call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'},
3646	      \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], ' ')
3647  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3648  call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'},
3649	      \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], 'r')
3650  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
3651
3652  call writefile(["F8:80:L80", "F8:81:L81"], "Xone")
3653  Xfile Xone
3654  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3655  Xaddfile Xone
3656  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
3657
3658  " Test case for updating a non-current quickfix list
3659  call g:Xsetlist([], 'f')
3660  Xexpr "F1:1:L1"
3661  Xexpr "F2:2:L2"
3662  call g:Xsetlist([], 'a', {'nr' : 1, "lines" : ["F10:10:L10"]})
3663  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3664  call assert_equal(2, g:Xgetlist({'nr' : 1, 'changedtick' : 0}).changedtick)
3665
3666  call delete("Xone")
3667endfunc
3668
3669func Test_qf_tick()
3670  call Xqftick_tests('c')
3671  call Xqftick_tests('l')
3672endfunc
3673
3674" Test helpgrep with lang specifier
3675func Xtest_helpgrep_with_lang_specifier(cchar)
3676  call s:setup_commands(a:cchar)
3677  Xhelpgrep Vim@en
3678  call assert_equal('help', &filetype)
3679  call assert_notequal(0, g:Xgetlist({'nr' : '$'}).nr)
3680  new | only
3681endfunc
3682
3683func Test_helpgrep_with_lang_specifier()
3684  call Xtest_helpgrep_with_lang_specifier('c')
3685  call Xtest_helpgrep_with_lang_specifier('l')
3686endfunc
3687
3688" The following test used to crash Vim.
3689" Open the location list window and close the regular window associated with
3690" the location list. When the garbage collection runs now, it incorrectly
3691" marks the location list context as not in use and frees the context.
3692func Test_ll_window_ctx()
3693  call setloclist(0, [], 'f')
3694  call setloclist(0, [], 'a', {'context' : []})
3695  lopen | only
3696  call test_garbagecollect_now()
3697  echo getloclist(0, {'context' : 1}).context
3698  enew | only
3699endfunc
3700
3701" The following test used to crash vim
3702func Test_lfile_crash()
3703  sp Xtest
3704  au QuickFixCmdPre * bw
3705  call assert_fails('lfile', 'E40:')
3706  au! QuickFixCmdPre
3707endfunc
3708
3709" The following test used to crash vim
3710func Test_lbuffer_crash()
3711  sv Xtest
3712  augroup QF_Test
3713    au!
3714    au * * bw
3715  augroup END
3716  lbuffer
3717  augroup QF_Test
3718    au!
3719  augroup END
3720endfunc
3721
3722" The following test used to crash vim
3723func Test_lexpr_crash()
3724  augroup QF_Test
3725    au!
3726    au * * call setloclist(0, [], 'f')
3727  augroup END
3728  lexpr ""
3729  augroup QF_Test
3730    au!
3731  augroup END
3732
3733  enew | only
3734  augroup QF_Test
3735    au!
3736    au BufNew * call setloclist(0, [], 'f')
3737  augroup END
3738  lexpr 'x:1:x'
3739  augroup QF_Test
3740    au!
3741  augroup END
3742
3743  enew | only
3744  lexpr ''
3745  lopen
3746  augroup QF_Test
3747    au!
3748    au FileType * call setloclist(0, [], 'f')
3749  augroup END
3750  lexpr ''
3751  augroup QF_Test
3752    au!
3753  augroup END
3754endfunc
3755
3756" The following test used to crash Vim
3757func Test_lvimgrep_crash()
3758  sv Xtest
3759  augroup QF_Test
3760    au!
3761    au * * call setloclist(0, [], 'f')
3762  augroup END
3763  lvimgrep quickfix test_quickfix.vim
3764  augroup QF_Test
3765    au!
3766  augroup END
3767
3768  new | only
3769  augroup QF_Test
3770    au!
3771    au BufEnter * call setloclist(0, [], 'r')
3772  augroup END
3773  call assert_fails('lvimgrep Test_lvimgrep_crash *', 'E926:')
3774  augroup QF_Test
3775    au!
3776  augroup END
3777
3778  enew | only
3779endfunc
3780
3781func Test_lvimgrep_crash2()
3782  au BufNewFile x sfind
3783  call assert_fails('lvimgrep x x', 'E471:')
3784  call assert_fails('lvimgrep x x x', 'E471:')
3785
3786  au! BufNewFile
3787endfunc
3788
3789" Test for the position of the quickfix and location list window
3790func Test_qfwin_pos()
3791  " Open two windows
3792  new | only
3793  new
3794  cexpr ['F1:10:L10']
3795  copen
3796  " Quickfix window should be the bottom most window
3797  call assert_equal(3, winnr())
3798  close
3799  " Open at the very top
3800  wincmd t
3801  topleft copen
3802  call assert_equal(1, winnr())
3803  close
3804  " open left of the current window
3805  wincmd t
3806  below new
3807  leftabove copen
3808  call assert_equal(2, winnr())
3809  close
3810  " open right of the current window
3811  rightbelow copen
3812  call assert_equal(3, winnr())
3813  close
3814endfunc
3815
3816" Tests for quickfix/location lists changed by autocommands when
3817" :vimgrep/:lvimgrep commands are running.
3818func Test_vimgrep_autocmd()
3819  call setqflist([], 'f')
3820  call writefile(['stars'], 'Xtest1.txt')
3821  call writefile(['stars'], 'Xtest2.txt')
3822
3823  " Test 1:
3824  " When searching for a pattern using :vimgrep, if the quickfix list is
3825  " changed by an autocmd, the results should be added to the correct quickfix
3826  " list.
3827  autocmd BufRead Xtest2.txt cexpr '' | cexpr ''
3828  silent vimgrep stars Xtest*.txt
3829  call assert_equal(1, getqflist({'nr' : 0}).nr)
3830  call assert_equal(3, getqflist({'nr' : '$'}).nr)
3831  call assert_equal('Xtest2.txt', bufname(getqflist()[1].bufnr))
3832  au! BufRead Xtest2.txt
3833
3834  " Test 2:
3835  " When searching for a pattern using :vimgrep, if the quickfix list is
3836  " freed, then a error should be given.
3837  silent! %bwipe!
3838  call setqflist([], 'f')
3839  autocmd BufRead Xtest2.txt for i in range(10) | cexpr '' | endfor
3840  call assert_fails('vimgrep stars Xtest*.txt', 'E925:')
3841  au! BufRead Xtest2.txt
3842
3843  " Test 3:
3844  " When searching for a pattern using :lvimgrep, if the location list is
3845  " freed, then the command should error out.
3846  silent! %bwipe!
3847  let g:save_winid = win_getid()
3848  autocmd BufRead Xtest2.txt call setloclist(g:save_winid, [], 'f')
3849  call assert_fails('lvimgrep stars Xtest*.txt', 'E926:')
3850  au! BufRead Xtest2.txt
3851
3852  call delete('Xtest1.txt')
3853  call delete('Xtest2.txt')
3854  call setqflist([], 'f')
3855endfunc
3856
3857" Test for an autocmd changing the current directory when running vimgrep
3858func Xvimgrep_autocmd_cd(cchar)
3859  call s:setup_commands(a:cchar)
3860
3861  %bwipe
3862  let save_cwd = getcwd()
3863
3864  augroup QF_Test
3865    au!
3866    autocmd BufRead * silent cd %:p:h
3867  augroup END
3868
3869  10Xvimgrep /vim/ Xdir/**
3870  let l = g:Xgetlist()
3871  call assert_equal('f1.txt', bufname(l[0].bufnr))
3872  call assert_equal('f2.txt', fnamemodify(bufname(l[2].bufnr), ':t'))
3873
3874  augroup QF_Test
3875    au!
3876  augroup END
3877
3878  exe 'cd ' . save_cwd
3879endfunc
3880
3881func Test_vimgrep_autocmd_cd()
3882  call mkdir('Xdir/a', 'p')
3883  call mkdir('Xdir/b', 'p')
3884  call writefile(['a_L1_vim', 'a_L2_vim'], 'Xdir/a/f1.txt')
3885  call writefile(['b_L1_vim', 'b_L2_vim'], 'Xdir/b/f2.txt')
3886  call Xvimgrep_autocmd_cd('c')
3887  call Xvimgrep_autocmd_cd('l')
3888  %bwipe
3889  call delete('Xdir', 'rf')
3890endfunc
3891
3892" The following test used to crash Vim
3893func Test_lhelpgrep_autocmd()
3894  lhelpgrep quickfix
3895  autocmd QuickFixCmdPost * call setloclist(0, [], 'f')
3896  lhelpgrep buffer
3897  call assert_equal('help', &filetype)
3898  call assert_equal(0, getloclist(0, {'nr' : '$'}).nr)
3899  lhelpgrep tabpage
3900  call assert_equal('help', &filetype)
3901  call assert_equal(1, getloclist(0, {'nr' : '$'}).nr)
3902  au! QuickFixCmdPost
3903
3904  new | only
3905  augroup QF_Test
3906    au!
3907    au BufEnter * call setqflist([], 'f')
3908  augroup END
3909  call assert_fails('helpgrep quickfix', 'E925:')
3910  augroup QF_Test
3911    au! BufEnter
3912  augroup END
3913
3914  new | only
3915  augroup QF_Test
3916    au!
3917    au BufEnter * call setqflist([], 'r')
3918  augroup END
3919  call assert_fails('helpgrep quickfix', 'E925:')
3920  augroup QF_Test
3921    au! BufEnter
3922  augroup END
3923
3924  new | only
3925  augroup QF_Test
3926    au!
3927    au BufEnter * call setloclist(0, [], 'r')
3928  augroup END
3929  call assert_fails('lhelpgrep quickfix', 'E926:')
3930  augroup QF_Test
3931    au! BufEnter
3932  augroup END
3933
3934  new | only
3935endfunc
3936
3937" Test for shortening/simplifying the file name when opening the
3938" quickfix window or when displaying the quickfix list
3939func Test_shorten_fname()
3940  CheckUnix
3941  %bwipe
3942  " Create a quickfix list with a absolute path filename
3943  let fname = getcwd() . '/test_quickfix.vim'
3944  call setqflist([], ' ', {'lines':[fname . ":20:Line20"], 'efm':'%f:%l:%m'})
3945  call assert_equal(fname, bufname('test_quickfix.vim'))
3946  " Opening the quickfix window should simplify the file path
3947  cwindow
3948  call assert_equal('test_quickfix.vim', bufname('test_quickfix.vim'))
3949  cclose
3950  %bwipe
3951  " Create a quickfix list with a absolute path filename
3952  call setqflist([], ' ', {'lines':[fname . ":20:Line20"], 'efm':'%f:%l:%m'})
3953  call assert_equal(fname, bufname('test_quickfix.vim'))
3954  " Displaying the quickfix list should simplify the file path
3955  silent! clist
3956  call assert_equal('test_quickfix.vim', bufname('test_quickfix.vim'))
3957endfunc
3958
3959" Quickfix title tests
3960" In the below tests, 'exe "cmd"' is used to invoke the quickfix commands.
3961" Otherwise due to indentation, the title is set with spaces at the beginning
3962" of the command.
3963func Test_qftitle()
3964  call writefile(["F1:1:Line1"], 'Xerr')
3965
3966  " :cexpr
3967  exe "cexpr readfile('Xerr')"
3968  call assert_equal(":cexpr readfile('Xerr')", getqflist({'title' : 1}).title)
3969
3970  " :cgetexpr
3971  exe "cgetexpr readfile('Xerr')"
3972  call assert_equal(":cgetexpr readfile('Xerr')",
3973					\ getqflist({'title' : 1}).title)
3974
3975  " :caddexpr
3976  call setqflist([], 'f')
3977  exe "caddexpr readfile('Xerr')"
3978  call assert_equal(":caddexpr readfile('Xerr')",
3979					\ getqflist({'title' : 1}).title)
3980
3981  " :cbuffer
3982  new Xerr
3983  exe "cbuffer"
3984  call assert_equal(':cbuffer (Xerr)', getqflist({'title' : 1}).title)
3985
3986  " :cgetbuffer
3987  edit Xerr
3988  exe "cgetbuffer"
3989  call assert_equal(':cgetbuffer (Xerr)', getqflist({'title' : 1}).title)
3990
3991  " :caddbuffer
3992  call setqflist([], 'f')
3993  edit Xerr
3994  exe "caddbuffer"
3995  call assert_equal(':caddbuffer (Xerr)', getqflist({'title' : 1}).title)
3996
3997  " :cfile
3998  exe "cfile Xerr"
3999  call assert_equal(':cfile Xerr', getqflist({'title' : 1}).title)
4000
4001  " :cgetfile
4002  exe "cgetfile Xerr"
4003  call assert_equal(':cgetfile Xerr', getqflist({'title' : 1}).title)
4004
4005  " :caddfile
4006  call setqflist([], 'f')
4007  exe "caddfile Xerr"
4008  call assert_equal(':caddfile Xerr', getqflist({'title' : 1}).title)
4009
4010  " :grep
4011  set grepprg=internal
4012  exe "grep F1 Xerr"
4013  call assert_equal(':grep F1 Xerr', getqflist({'title' : 1}).title)
4014
4015  " :grepadd
4016  call setqflist([], 'f')
4017  exe "grepadd F1 Xerr"
4018  call assert_equal(':grepadd F1 Xerr', getqflist({'title' : 1}).title)
4019  set grepprg&vim
4020
4021  " :vimgrep
4022  exe "vimgrep F1 Xerr"
4023  call assert_equal(':vimgrep F1 Xerr', getqflist({'title' : 1}).title)
4024
4025  " :vimgrepadd
4026  call setqflist([], 'f')
4027  exe "vimgrepadd F1 Xerr"
4028  call assert_equal(':vimgrepadd F1 Xerr', getqflist({'title' : 1}).title)
4029
4030  call setqflist(['F1:10:L10'], ' ')
4031  call assert_equal(':setqflist()', getqflist({'title' : 1}).title)
4032
4033  call setqflist([], 'f')
4034  call setqflist(['F1:10:L10'], 'a')
4035  call assert_equal(':setqflist()', getqflist({'title' : 1}).title)
4036
4037  call setqflist([], 'f')
4038  call setqflist(['F1:10:L10'], 'r')
4039  call assert_equal(':setqflist()', getqflist({'title' : 1}).title)
4040
4041  close
4042  call delete('Xerr')
4043
4044  call setqflist([], ' ', {'title' : 'Errors'})
4045  copen
4046  call assert_equal('Errors', w:quickfix_title)
4047  call setqflist([], 'r', {'items' : [{'filename' : 'a.c', 'lnum' : 10}]})
4048  call assert_equal('Errors', w:quickfix_title)
4049  cclose
4050endfunc
4051
4052func Test_lbuffer_with_bwipe()
4053  new
4054  new
4055  augroup nasty
4056    au * * bwipe
4057  augroup END
4058  lbuffer
4059  augroup nasty
4060    au!
4061  augroup END
4062endfunc
4063
4064" Test for an autocmd freeing the quickfix/location list when cexpr/lexpr is
4065" running
4066func Xexpr_acmd_freelist(cchar)
4067  call s:setup_commands(a:cchar)
4068
4069  " This was using freed memory.
4070  augroup nasty
4071    au * * call g:Xsetlist([], 'f')
4072  augroup END
4073  Xexpr "x"
4074  augroup nasty
4075    au!
4076  augroup END
4077endfunc
4078
4079func Test_cexpr_acmd_freelist()
4080  call Xexpr_acmd_freelist('c')
4081  call Xexpr_acmd_freelist('l')
4082endfunc
4083
4084" Test for commands that create a new quickfix/location list and jump to the
4085" first error automatically.
4086func Xjumpto_first_error_test(cchar)
4087  call s:setup_commands(a:cchar)
4088
4089  call s:create_test_file('Xtestfile1')
4090  call s:create_test_file('Xtestfile2')
4091  let l = ['Xtestfile1:2:Line2', 'Xtestfile2:4:Line4']
4092
4093  " Test for cexpr/lexpr
4094  enew
4095  Xexpr l
4096  call assert_equal('Xtestfile1', @%)
4097  call assert_equal(2, line('.'))
4098
4099  " Test for cfile/lfile
4100  enew
4101  call writefile(l, 'Xerr')
4102  Xfile Xerr
4103  call assert_equal('Xtestfile1', @%)
4104  call assert_equal(2, line('.'))
4105
4106  " Test for cbuffer/lbuffer
4107  edit Xerr
4108  Xbuffer
4109  call assert_equal('Xtestfile1', @%)
4110  call assert_equal(2, line('.'))
4111
4112  call delete('Xerr')
4113  call delete('Xtestfile1')
4114  call delete('Xtestfile2')
4115endfunc
4116
4117func Test_jumpto_first_error()
4118  call Xjumpto_first_error_test('c')
4119  call Xjumpto_first_error_test('l')
4120endfunc
4121
4122" Test for a quickfix autocmd changing the quickfix/location list before
4123" jumping to the first error in the new list.
4124func Xautocmd_changelist(cchar)
4125  call s:setup_commands(a:cchar)
4126
4127  " Test for cfile/lfile
4128  call s:create_test_file('Xtestfile1')
4129  call s:create_test_file('Xtestfile2')
4130  Xexpr 'Xtestfile1:2:Line2'
4131  autocmd QuickFixCmdPost * Xolder
4132  call writefile(['Xtestfile2:4:Line4'], 'Xerr')
4133  Xfile Xerr
4134  call assert_equal('Xtestfile2', @%)
4135  call assert_equal(4, line('.'))
4136  autocmd! QuickFixCmdPost
4137
4138  " Test for cbuffer/lbuffer
4139  call g:Xsetlist([], 'f')
4140  Xexpr 'Xtestfile1:2:Line2'
4141  autocmd QuickFixCmdPost * Xolder
4142  call writefile(['Xtestfile2:4:Line4'], 'Xerr')
4143  edit Xerr
4144  Xbuffer
4145  call assert_equal('Xtestfile2', @%)
4146  call assert_equal(4, line('.'))
4147  autocmd! QuickFixCmdPost
4148
4149  " Test for cexpr/lexpr
4150  call g:Xsetlist([], 'f')
4151  Xexpr 'Xtestfile1:2:Line2'
4152  autocmd QuickFixCmdPost * Xolder
4153  Xexpr 'Xtestfile2:4:Line4'
4154  call assert_equal('Xtestfile2', @%)
4155  call assert_equal(4, line('.'))
4156  autocmd! QuickFixCmdPost
4157
4158  " The grepprg may not be set on non-Unix systems
4159  if has('unix')
4160    " Test for grep/lgrep
4161    call g:Xsetlist([], 'f')
4162    Xexpr 'Xtestfile1:2:Line2'
4163    autocmd QuickFixCmdPost * Xolder
4164    silent Xgrep Line5 Xtestfile2
4165    call assert_equal('Xtestfile2', @%)
4166    call assert_equal(5, line('.'))
4167    autocmd! QuickFixCmdPost
4168  endif
4169
4170  " Test for vimgrep/lvimgrep
4171  call g:Xsetlist([], 'f')
4172  Xexpr 'Xtestfile1:2:Line2'
4173  autocmd QuickFixCmdPost * Xolder
4174  silent Xvimgrep Line5 Xtestfile2
4175  call assert_equal('Xtestfile2', @%)
4176  call assert_equal(5, line('.'))
4177  autocmd! QuickFixCmdPost
4178
4179  " Test for autocommands clearing the quickfix list before jumping to the
4180  " first error. This should not result in an error
4181  autocmd QuickFixCmdPost * call g:Xsetlist([], 'r')
4182  let v:errmsg = ''
4183  " Test for cfile/lfile
4184  Xfile Xerr
4185  call assert_true(v:errmsg !~# 'E42:')
4186  " Test for cbuffer/lbuffer
4187  edit Xerr
4188  Xbuffer
4189  call assert_true(v:errmsg !~# 'E42:')
4190  " Test for cexpr/lexpr
4191  Xexpr 'Xtestfile2:4:Line4'
4192  call assert_true(v:errmsg !~# 'E42:')
4193  " Test for grep/lgrep
4194  " The grepprg may not be set on non-Unix systems
4195  if has('unix')
4196    silent Xgrep Line5 Xtestfile2
4197    call assert_true(v:errmsg !~# 'E42:')
4198  endif
4199  " Test for vimgrep/lvimgrep
4200  call assert_fails('silent Xvimgrep Line5 Xtestfile2', 'E480:')
4201  autocmd! QuickFixCmdPost
4202
4203  call delete('Xerr')
4204  call delete('Xtestfile1')
4205  call delete('Xtestfile2')
4206endfunc
4207
4208func Test_autocmd_changelist()
4209  call Xautocmd_changelist('c')
4210  call Xautocmd_changelist('l')
4211endfunc
4212
4213" Tests for the ':filter /pat/ clist' command
4214func Test_filter_clist()
4215  cexpr ['Xfile1:10:10:Line 10', 'Xfile2:15:15:Line 15']
4216  call assert_equal([' 2 Xfile2:15 col 15: Line 15'],
4217			\ split(execute('filter /Line 15/ clist'), "\n"))
4218  call assert_equal([' 1 Xfile1:10 col 10: Line 10'],
4219			\ split(execute('filter /Xfile1/ clist'), "\n"))
4220  call assert_equal([], split(execute('filter /abc/ clist'), "\n"))
4221
4222  call setqflist([{'module' : 'abc', 'pattern' : 'pat1'},
4223			\ {'module' : 'pqr', 'pattern' : 'pat2'}], ' ')
4224  call assert_equal([' 2 pqr:pat2:  '],
4225			\ split(execute('filter /pqr/ clist'), "\n"))
4226  call assert_equal([' 1 abc:pat1:  '],
4227			\ split(execute('filter /pat1/ clist'), "\n"))
4228endfunc
4229
4230" Tests for the "CTRL-W <CR>" command.
4231func Xview_result_split_tests(cchar)
4232  call s:setup_commands(a:cchar)
4233
4234  " Test that "CTRL-W <CR>" in a qf/ll window fails with empty list.
4235  call g:Xsetlist([])
4236  Xopen
4237  let l:win_count = winnr('$')
4238  call assert_fails('execute "normal! \<C-W>\<CR>"', 'E42:')
4239  call assert_equal(l:win_count, winnr('$'))
4240  Xclose
4241endfunc
4242
4243func Test_view_result_split()
4244  call Xview_result_split_tests('c')
4245  call Xview_result_split_tests('l')
4246endfunc
4247
4248" Test that :cc sets curswant
4249func Test_curswant()
4250  helpgrep quickfix
4251  normal! llll
4252  1cc
4253  call assert_equal(getcurpos()[4], virtcol('.'))
4254  cclose | helpclose
4255endfunc
4256
4257" Test for opening a file from the quickfix window using CTRL-W <Enter>
4258" doesn't leave an empty buffer around.
4259func Test_splitview()
4260  call s:create_test_file('Xtestfile1')
4261  call s:create_test_file('Xtestfile2')
4262  new | only
4263  let last_bufnr = bufnr('Test_sv_1', 1)
4264  let l = ['Xtestfile1:2:Line2', 'Xtestfile2:4:Line4']
4265  cgetexpr l
4266  copen
4267  let numbufs = len(getbufinfo())
4268  exe "normal \<C-W>\<CR>"
4269  copen
4270  exe "normal j\<C-W>\<CR>"
4271  " Make sure new empty buffers are not created
4272  call assert_equal(numbufs, len(getbufinfo()))
4273  " Creating a new buffer should use the next available buffer number
4274  call assert_equal(last_bufnr + 4, bufnr("Test_sv_2", 1))
4275  bwipe Test_sv_1
4276  bwipe Test_sv_2
4277  new | only
4278
4279  " When split opening files from location list window, make sure that two
4280  " windows doesn't refer to the same location list
4281  lgetexpr l
4282  let locid = getloclist(0, {'id' : 0}).id
4283  lopen
4284  exe "normal \<C-W>\<CR>"
4285  call assert_notequal(locid, getloclist(0, {'id' : 0}).id)
4286  call assert_equal(0, getloclist(0, {'winid' : 0}).winid)
4287  new | only
4288
4289  " When split opening files from a helpgrep location list window, a new help
4290  " window should be opened with a copy of the location list.
4291  lhelpgrep window
4292  let locid = getloclist(0, {'id' : 0}).id
4293  lwindow
4294  exe "normal j\<C-W>\<CR>"
4295  call assert_notequal(locid, getloclist(0, {'id' : 0}).id)
4296  call assert_equal(0, getloclist(0, {'winid' : 0}).winid)
4297  new | only
4298
4299  " Using :split or :vsplit from a quickfix window should behave like a :new
4300  " or a :vnew command
4301  copen
4302  split
4303  call assert_equal(3, winnr('$'))
4304  let l = getwininfo()
4305  call assert_equal([0, 0, 1], [l[0].quickfix, l[1].quickfix, l[2].quickfix])
4306  close
4307  copen
4308  vsplit
4309  let l = getwininfo()
4310  call assert_equal([0, 0, 1], [l[0].quickfix, l[1].quickfix, l[2].quickfix])
4311  new | only
4312
4313  call delete('Xtestfile1')
4314  call delete('Xtestfile2')
4315endfunc
4316
4317" Test for parsing entries using visual screen column
4318func Test_viscol()
4319  enew
4320  call writefile(["Col1\tCol2\tCol3"], 'Xfile1')
4321  edit Xfile1
4322
4323  " Use byte offset for column number
4324  set efm&
4325  cexpr "Xfile1:1:5:XX\nXfile1:1:9:YY\nXfile1:1:20:ZZ"
4326  call assert_equal([5, 8], [col('.'), virtcol('.')])
4327  cnext
4328  call assert_equal([9, 12], [col('.'), virtcol('.')])
4329  cnext
4330  call assert_equal([14, 20], [col('.'), virtcol('.')])
4331
4332  " Use screen column offset for column number
4333  set efm=%f:%l:%v:%m
4334  cexpr "Xfile1:1:8:XX\nXfile1:1:12:YY\nXfile1:1:20:ZZ"
4335  call assert_equal([5, 8], [col('.'), virtcol('.')])
4336  cnext
4337  call assert_equal([9, 12], [col('.'), virtcol('.')])
4338  cnext
4339  call assert_equal([14, 20], [col('.'), virtcol('.')])
4340  cexpr "Xfile1:1:6:XX\nXfile1:1:15:YY\nXfile1:1:24:ZZ"
4341  call assert_equal([5, 8], [col('.'), virtcol('.')])
4342  cnext
4343  call assert_equal([10, 16], [col('.'), virtcol('.')])
4344  cnext
4345  call assert_equal([14, 20], [col('.'), virtcol('.')])
4346
4347  enew
4348  call writefile(["Col1\täü\töß\tCol4"], 'Xfile1')
4349
4350  " Use byte offset for column number
4351  set efm&
4352  cexpr "Xfile1:1:8:XX\nXfile1:1:11:YY\nXfile1:1:16:ZZ"
4353  call assert_equal([8, 10], [col('.'), virtcol('.')])
4354  cnext
4355  call assert_equal([11, 17], [col('.'), virtcol('.')])
4356  cnext
4357  call assert_equal([16, 25], [col('.'), virtcol('.')])
4358
4359  " Use screen column offset for column number
4360  set efm=%f:%l:%v:%m
4361  cexpr "Xfile1:1:10:XX\nXfile1:1:17:YY\nXfile1:1:25:ZZ"
4362  call assert_equal([8, 10], [col('.'), virtcol('.')])
4363  cnext
4364  call assert_equal([11, 17], [col('.'), virtcol('.')])
4365  cnext
4366  call assert_equal([16, 25], [col('.'), virtcol('.')])
4367
4368  enew | only
4369  set efm&
4370  call delete('Xfile1')
4371endfunc
4372
4373" Test for the quickfix window buffer
4374func Xqfbuf_test(cchar)
4375  call s:setup_commands(a:cchar)
4376
4377  " Quickfix buffer should be reused across closing and opening a quickfix
4378  " window
4379  Xexpr "F1:10:Line10"
4380  Xopen
4381  let qfbnum = bufnr('')
4382  Xclose
4383  " Even after the quickfix window is closed, the buffer should be loaded
4384  call assert_true(bufloaded(qfbnum))
4385  call assert_true(qfbnum, g:Xgetlist({'qfbufnr' : 0}).qfbufnr)
4386  Xopen
4387  " Buffer should be reused when opening the window again
4388  call assert_equal(qfbnum, bufnr(''))
4389  Xclose
4390
4391  if a:cchar == 'l'
4392    %bwipe
4393    " For a location list, when both the file window and the location list
4394    " window for the list are closed, then the buffer should be freed.
4395    new | only
4396    lexpr "F1:10:Line10"
4397    let wid = win_getid()
4398    lopen
4399    let qfbnum = bufnr('')
4400    call assert_match(qfbnum . ' %a-  "\[Location List]"', execute('ls'))
4401    close
4402    " When the location list window is closed, the buffer name should not
4403    " change to 'Quickfix List'
4404    call assert_match(qfbnum . 'u h-  "\[Location List]"', execute('ls!'))
4405    call assert_true(bufloaded(qfbnum))
4406
4407    " After deleting a location list buffer using ":bdelete", opening the
4408    " location list window should mark the buffer as a location list buffer.
4409    exe "bdelete " . qfbnum
4410    lopen
4411    call assert_equal("quickfix", &buftype)
4412    call assert_equal(1, getwininfo(win_getid(winnr()))[0].loclist)
4413    call assert_equal(wid, getloclist(0, {'filewinid' : 0}).filewinid)
4414    call assert_false(&swapfile)
4415    lclose
4416
4417    " When the location list is cleared for the window, the buffer should be
4418    " removed
4419    call setloclist(0, [], 'f')
4420    call assert_false(bufexists(qfbnum))
4421    call assert_equal(0, getloclist(0, {'qfbufnr' : 0}).qfbufnr)
4422
4423    " When the location list is freed with the location list window open, the
4424    " location list buffer should not be lost. It should be reused when the
4425    " location list is again populated.
4426    lexpr "F1:10:Line10"
4427    lopen
4428    let wid = win_getid()
4429    let qfbnum = bufnr('')
4430    wincmd p
4431    call setloclist(0, [], 'f')
4432    lexpr "F1:10:Line10"
4433    lopen
4434    call assert_equal(wid, win_getid())
4435    call assert_equal(qfbnum, bufnr(''))
4436    lclose
4437
4438    " When the window with the location list is closed, the buffer should be
4439    " removed
4440    new | only
4441    call assert_false(bufexists(qfbnum))
4442  endif
4443endfunc
4444
4445func Test_qfbuf()
4446  call Xqfbuf_test('c')
4447  call Xqfbuf_test('l')
4448endfunc
4449
4450" If there is an autocmd to use only one window, then opening the location
4451" list window used to crash Vim.
4452func Test_winonly_autocmd()
4453  call s:create_test_file('Xtest1')
4454  " Autocmd to show only one Vim window at a time
4455  autocmd WinEnter * only
4456  new
4457  " Load the location list
4458  lexpr "Xtest1:5:Line5\nXtest1:10:Line10\nXtest1:15:Line15"
4459  let loclistid = getloclist(0, {'id' : 0}).id
4460  " Open the location list window. Only this window will be shown and the file
4461  " window is closed.
4462  lopen
4463  call assert_equal(loclistid, getloclist(0, {'id' : 0}).id)
4464  " Jump to an entry in the location list and make sure that the cursor is
4465  " positioned correctly.
4466  ll 3
4467  call assert_equal(loclistid, getloclist(0, {'id' : 0}).id)
4468  call assert_equal('Xtest1', @%)
4469  call assert_equal(15, line('.'))
4470  " Cleanup
4471  autocmd! WinEnter
4472  new | only
4473  call delete('Xtest1')
4474endfunc
4475
4476" Test to make sure that an empty quickfix buffer is not reused for loading
4477" a normal buffer.
4478func Test_empty_qfbuf()
4479  enew | only
4480  call writefile(["Test"], 'Xfile1')
4481  call setqflist([], 'f')
4482  copen | only
4483  let qfbuf = bufnr('')
4484  edit Xfile1
4485  call assert_notequal(qfbuf, bufnr(''))
4486  enew
4487  call delete('Xfile1')
4488endfunc
4489
4490" Test for the :cbelow, :cabove, :lbelow and :labove commands.
4491" And for the :cafter, :cbefore, :lafter and :lbefore commands.
4492func Xtest_below(cchar)
4493  call s:setup_commands(a:cchar)
4494
4495  " No quickfix/location list
4496  call assert_fails('Xbelow', 'E42:')
4497  call assert_fails('Xabove', 'E42:')
4498  call assert_fails('Xbefore', 'E42:')
4499  call assert_fails('Xafter', 'E42:')
4500
4501  " Empty quickfix/location list
4502  call g:Xsetlist([])
4503  call assert_fails('Xbelow', 'E42:')
4504  call assert_fails('Xabove', 'E42:')
4505  call assert_fails('Xbefore', 'E42:')
4506  call assert_fails('Xafter', 'E42:')
4507
4508  call s:create_test_file('X1')
4509  call s:create_test_file('X2')
4510  call s:create_test_file('X3')
4511  call s:create_test_file('X4')
4512
4513  " Invalid entries
4514  edit X1
4515  call g:Xsetlist(["E1", "E2"])
4516  call assert_fails('Xbelow', 'E42:')
4517  call assert_fails('Xabove', 'E42:')
4518  call assert_fails('3Xbelow', 'E42:')
4519  call assert_fails('4Xabove', 'E42:')
4520  call assert_fails('Xbefore', 'E42:')
4521  call assert_fails('Xafter', 'E42:')
4522  call assert_fails('3Xbefore', 'E42:')
4523  call assert_fails('4Xafter', 'E42:')
4524
4525  " Test the commands with various arguments
4526  Xexpr ["X1:5:3:L5", "X2:5:2:L5", "X2:10:3:L10", "X2:15:4:L15", "X3:3:5:L3"]
4527  edit +7 X2
4528  Xabove
4529  call assert_equal(['X2', 5], [@%, line('.')])
4530  call assert_fails('Xabove', 'E553:')
4531  normal 7G
4532  Xbefore
4533  call assert_equal(['X2', 5, 2], [@%, line('.'), col('.')])
4534  call assert_fails('Xbefore', 'E553:')
4535
4536  normal 2j
4537  Xbelow
4538  call assert_equal(['X2', 10], [@%, line('.')])
4539  normal 7G
4540  Xafter
4541  call assert_equal(['X2', 10, 3], [@%, line('.'), col('.')])
4542
4543  " Last error in this file
4544  Xbelow 99
4545  call assert_equal(['X2', 15], [@%, line('.')])
4546  call assert_fails('Xbelow', 'E553:')
4547  normal gg
4548  Xafter 99
4549  call assert_equal(['X2', 15, 4], [@%, line('.'), col('.')])
4550  call assert_fails('Xafter', 'E553:')
4551
4552  " First error in this file
4553  Xabove 99
4554  call assert_equal(['X2', 5], [@%, line('.')])
4555  call assert_fails('Xabove', 'E553:')
4556  normal G
4557  Xbefore 99
4558  call assert_equal(['X2', 5, 2], [@%, line('.'), col('.')])
4559  call assert_fails('Xbefore', 'E553:')
4560
4561  normal gg
4562  Xbelow 2
4563  call assert_equal(['X2', 10], [@%, line('.')])
4564  normal gg
4565  Xafter 2
4566  call assert_equal(['X2', 10, 3], [@%, line('.'), col('.')])
4567
4568  normal G
4569  Xabove 2
4570  call assert_equal(['X2', 10], [@%, line('.')])
4571  normal G
4572  Xbefore 2
4573  call assert_equal(['X2', 10, 3], [@%, line('.'), col('.')])
4574
4575  edit X4
4576  call assert_fails('Xabove', 'E42:')
4577  call assert_fails('Xbelow', 'E42:')
4578  call assert_fails('Xbefore', 'E42:')
4579  call assert_fails('Xafter', 'E42:')
4580  if a:cchar == 'l'
4581    " If a buffer has location list entries from some other window but not
4582    " from the current window, then the commands should fail.
4583    edit X1 | split | call setloclist(0, [], 'f')
4584    call assert_fails('Xabove', 'E776:')
4585    call assert_fails('Xbelow', 'E776:')
4586    call assert_fails('Xbefore', 'E776:')
4587    call assert_fails('Xafter', 'E776:')
4588    close
4589  endif
4590
4591  " Test for lines with multiple quickfix entries
4592  Xexpr ["X1:5:L5", "X2:5:1:L5_1", "X2:5:2:L5_2", "X2:5:3:L5_3",
4593	      \ "X2:10:1:L10_1", "X2:10:2:L10_2", "X2:10:3:L10_3",
4594	      \ "X2:15:1:L15_1", "X2:15:2:L15_2", "X2:15:3:L15_3", "X3:3:L3"]
4595  edit +1 X2
4596  Xbelow 2
4597  call assert_equal(['X2', 10, 1], [@%, line('.'), col('.')])
4598  normal 1G
4599  Xafter 2
4600  call assert_equal(['X2', 5, 2], [@%, line('.'), col('.')])
4601
4602  normal gg
4603  Xbelow 99
4604  call assert_equal(['X2', 15, 1], [@%, line('.'), col('.')])
4605  normal gg
4606  Xafter 99
4607  call assert_equal(['X2', 15, 3], [@%, line('.'), col('.')])
4608
4609  normal G
4610  Xabove 2
4611  call assert_equal(['X2', 10, 1], [@%, line('.'), col('.')])
4612  normal G
4613  Xbefore 2
4614  call assert_equal(['X2', 15, 2], [@%, line('.'), col('.')])
4615
4616  normal G
4617  Xabove 99
4618  call assert_equal(['X2', 5, 1], [@%, line('.'), col('.')])
4619  normal G
4620  Xbefore 99
4621  call assert_equal(['X2', 5, 1], [@%, line('.'), col('.')])
4622
4623  normal 10G
4624  Xabove
4625  call assert_equal(['X2', 5, 1], [@%, line('.'), col('.')])
4626  normal 10G$
4627  2Xbefore
4628  call assert_equal(['X2', 10, 2], [@%, line('.'), col('.')])
4629
4630  normal 10G
4631  Xbelow
4632  call assert_equal(['X2', 15, 1], [@%, line('.'), col('.')])
4633  normal 9G
4634  5Xafter
4635  call assert_equal(['X2', 15, 2], [@%, line('.'), col('.')])
4636
4637  " Invalid range
4638  if a:cchar == 'c'
4639    call assert_fails('-2cbelow', 'E16:')
4640    call assert_fails('-2cafter', 'E16:')
4641  else
4642    call assert_fails('-2lbelow', 'E16:')
4643    call assert_fails('-2lafter', 'E16:')
4644  endif
4645
4646  call delete('X1')
4647  call delete('X2')
4648  call delete('X3')
4649  call delete('X4')
4650endfunc
4651
4652func Test_cbelow()
4653  call Xtest_below('c')
4654  call Xtest_below('l')
4655endfunc
4656
4657func Test_quickfix_count()
4658  let commands = [
4659	\ 'cNext',
4660	\ 'cNfile',
4661	\ 'cabove',
4662	\ 'cbelow',
4663	\ 'cfirst',
4664	\ 'clast',
4665	\ 'cnewer',
4666	\ 'cnext',
4667	\ 'cnfile',
4668	\ 'colder',
4669	\ 'cprevious',
4670	\ 'crewind',
4671	\
4672	\ 'lNext',
4673	\ 'lNfile',
4674	\ 'labove',
4675	\ 'lbelow',
4676	\ 'lfirst',
4677	\ 'llast',
4678	\ 'lnewer',
4679	\ 'lnext',
4680	\ 'lnfile',
4681	\ 'lolder',
4682	\ 'lprevious',
4683	\ 'lrewind',
4684	\ ]
4685  for cmd in commands
4686    call assert_fails('-1' .. cmd, 'E16:')
4687    call assert_fails('.' .. cmd, 'E16:')
4688    call assert_fails('%' .. cmd, 'E16:')
4689    call assert_fails('$' .. cmd, 'E16:')
4690  endfor
4691endfunc
4692
4693" Test for aborting quickfix commands using QuickFixCmdPre
4694func Xtest_qfcmd_abort(cchar)
4695  call s:setup_commands(a:cchar)
4696
4697  call g:Xsetlist([], 'f')
4698
4699  " cexpr/lexpr
4700  let e = ''
4701  try
4702    Xexpr ["F1:10:Line10", "F2:20:Line20"]
4703  catch /.*/
4704    let e = v:exception
4705  endtry
4706  call assert_equal('AbortCmd', e)
4707  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4708
4709  " cfile/lfile
4710  call writefile(["F1:10:Line10", "F2:20:Line20"], 'Xfile1')
4711  let e = ''
4712  try
4713    Xfile Xfile1
4714  catch /.*/
4715    let e = v:exception
4716  endtry
4717  call assert_equal('AbortCmd', e)
4718  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4719  call delete('Xfile1')
4720
4721  " cgetbuffer/lgetbuffer
4722  enew!
4723  call append(0, ["F1:10:Line10", "F2:20:Line20"])
4724  let e = ''
4725  try
4726    Xgetbuffer
4727  catch /.*/
4728    let e = v:exception
4729  endtry
4730  call assert_equal('AbortCmd', e)
4731  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4732  enew!
4733
4734  " vimgrep/lvimgrep
4735  let e = ''
4736  try
4737    Xvimgrep /func/ test_quickfix.vim
4738  catch /.*/
4739    let e = v:exception
4740  endtry
4741  call assert_equal('AbortCmd', e)
4742  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4743
4744  " helpgrep/lhelpgrep
4745  let e = ''
4746  try
4747    Xhelpgrep quickfix
4748  catch /.*/
4749    let e = v:exception
4750  endtry
4751  call assert_equal('AbortCmd', e)
4752  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4753
4754  " grep/lgrep
4755  if has('unix')
4756    let e = ''
4757    try
4758      silent Xgrep func test_quickfix.vim
4759    catch /.*/
4760      let e = v:exception
4761    endtry
4762    call assert_equal('AbortCmd', e)
4763    call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4764  endif
4765endfunc
4766
4767func Test_qfcmd_abort()
4768  augroup QF_Test
4769    au!
4770    autocmd  QuickFixCmdPre * throw "AbortCmd"
4771  augroup END
4772
4773  call Xtest_qfcmd_abort('c')
4774  call Xtest_qfcmd_abort('l')
4775
4776  augroup QF_Test
4777    au!
4778  augroup END
4779endfunc
4780
4781" Test for using a file in one of the parent directories.
4782func Test_search_in_dirstack()
4783  call mkdir('Xtestdir/a/b/c', 'p')
4784  let save_cwd = getcwd()
4785  call writefile(["X1_L1", "X1_L2"], 'Xtestdir/Xfile1')
4786  call writefile(["X2_L1", "X2_L2"], 'Xtestdir/a/Xfile2')
4787  call writefile(["X3_L1", "X3_L2"], 'Xtestdir/a/b/Xfile3')
4788  call writefile(["X4_L1", "X4_L2"], 'Xtestdir/a/b/c/Xfile4')
4789
4790  let lines = "Entering dir Xtestdir\n" .
4791	      \ "Entering dir a\n" .
4792	      \ "Entering dir b\n" .
4793	      \ "Xfile2:2:X2_L2\n" .
4794	      \ "Leaving dir a\n" .
4795	      \ "Xfile1:2:X1_L2\n" .
4796	      \ "Xfile3:1:X3_L1\n" .
4797	      \ "Entering dir c\n" .
4798	      \ "Xfile4:2:X4_L2\n" .
4799	      \ "Leaving dir c\n"
4800  set efm=%DEntering\ dir\ %f,%XLeaving\ dir\ %f,%f:%l:%m
4801  cexpr lines .. "Leaving dir Xtestdir|\n" | let next = 1
4802  call assert_equal(11, getqflist({'size' : 0}).size)
4803  call assert_equal(4, getqflist({'idx' : 0}).idx)
4804  call assert_equal('X2_L2', getline('.'))
4805  call assert_equal(1, next)
4806  cnext
4807  call assert_equal(6, getqflist({'idx' : 0}).idx)
4808  call assert_equal('X1_L2', getline('.'))
4809  cnext
4810  call assert_equal(7, getqflist({'idx' : 0}).idx)
4811  call assert_equal(1, line('$'))
4812  call assert_equal('', getline(1))
4813  cnext
4814  call assert_equal(9, getqflist({'idx' : 0}).idx)
4815  call assert_equal(1, line('$'))
4816  call assert_equal('', getline(1))
4817
4818  set efm&
4819  exe 'cd ' . save_cwd
4820  call delete('Xtestdir', 'rf')
4821endfunc
4822
4823" Test for :cquit
4824func Test_cquit()
4825  " Exit Vim with a non-zero value
4826  if RunVim([], ["cquit 7"], '')
4827    call assert_equal(7, v:shell_error)
4828  endif
4829
4830  if RunVim([], ["50cquit"], '')
4831    call assert_equal(50, v:shell_error)
4832  endif
4833
4834  " Exit Vim with default value
4835  if RunVim([], ["cquit"], '')
4836    call assert_equal(1, v:shell_error)
4837  endif
4838
4839  " Exit Vim with zero value
4840  if RunVim([], ["cquit 0"], '')
4841    call assert_equal(0, v:shell_error)
4842  endif
4843
4844  " Exit Vim with negative value
4845  call assert_fails('-3cquit', 'E16:')
4846endfunc
4847
4848" Test for getting a specific item from a quickfix list
4849func Xtest_getqflist_by_idx(cchar)
4850  call s:setup_commands(a:cchar)
4851  " Empty list
4852  call assert_equal([], g:Xgetlist({'idx' : 1, 'items' : 0}).items)
4853  Xexpr ['F1:10:L10', 'F1:20:L20']
4854  let l = g:Xgetlist({'idx' : 2, 'items' : 0}).items
4855  call assert_equal(bufnr('F1'), l[0].bufnr)
4856  call assert_equal(20, l[0].lnum)
4857  call assert_equal('L20', l[0].text)
4858  call assert_equal([], g:Xgetlist({'idx' : -1, 'items' : 0}).items)
4859  call assert_equal([], g:Xgetlist({'idx' : 3, 'items' : 0}).items)
4860  %bwipe!
4861endfunc
4862
4863func Test_getqflist_by_idx()
4864  call Xtest_getqflist_by_idx('c')
4865  call Xtest_getqflist_by_idx('l')
4866endfunc
4867
4868" Test for the 'quickfixtextfunc' setting
4869func Tqfexpr(info)
4870  if a:info.quickfix
4871    let qfl = getqflist({'id' : a:info.id, 'items' : 1}).items
4872  else
4873    let qfl = getloclist(a:info.winid, {'id' : a:info.id, 'items' : 1}).items
4874  endif
4875
4876  let l = []
4877  for idx in range(a:info.start_idx - 1, a:info.end_idx - 1)
4878    let e = qfl[idx]
4879    let s = ''
4880    if e.bufnr != 0
4881      let bname = bufname(e.bufnr)
4882      let s ..= fnamemodify(bname, ':.')
4883    endif
4884    let s ..= '-'
4885    let s ..= 'L' .. string(e.lnum) .. 'C' .. string(e.col) .. '-'
4886    let s ..= e.text
4887    call add(l, s)
4888  endfor
4889
4890  return l
4891endfunc
4892
4893func Xtest_qftextfunc(cchar)
4894  call s:setup_commands(a:cchar)
4895
4896  set efm=%f:%l:%c:%m
4897  set quickfixtextfunc=Tqfexpr
4898  call assert_equal('Tqfexpr', &quickfixtextfunc)
4899  call assert_equal('',
4900        \ g:Xgetlist({'quickfixtextfunc' : 1}).quickfixtextfunc)
4901  Xexpr ['F1:10:2:green', 'F1:20:4:blue']
4902  Xwindow
4903  call assert_equal('F1-L10C2-green', getline(1))
4904  call assert_equal('F1-L20C4-blue', getline(2))
4905  Xclose
4906  set quickfixtextfunc&vim
4907  Xwindow
4908  call assert_equal('F1|10 col 2| green', getline(1))
4909  call assert_equal('F1|20 col 4| blue', getline(2))
4910  Xclose
4911  set efm&
4912  set quickfixtextfunc&
4913
4914  " Test for per list 'quickfixtextfunc' setting
4915  func PerQfText(info)
4916    if a:info.quickfix
4917      let qfl = getqflist({'id' : a:info.id, 'items' : 1}).items
4918    else
4919      let qfl = getloclist(a:info.winid, {'id' : a:info.id, 'items' : 1}).items
4920    endif
4921    if empty(qfl)
4922      return []
4923    endif
4924    let l = []
4925    for idx in range(a:info.start_idx - 1, a:info.end_idx - 1)
4926      call add(l, 'Line ' .. qfl[idx].lnum .. ', Col ' .. qfl[idx].col)
4927    endfor
4928    return l
4929  endfunc
4930  set quickfixtextfunc=Tqfexpr
4931  call g:Xsetlist([], ' ', {'quickfixtextfunc' : "PerQfText"})
4932  Xaddexpr ['F1:10:2:green', 'F1:20:4:blue']
4933  Xwindow
4934  call assert_equal('Line 10, Col 2', getline(1))
4935  call assert_equal('Line 20, Col 4', getline(2))
4936  Xclose
4937  call assert_equal(function('PerQfText'),
4938        \ g:Xgetlist({'quickfixtextfunc' : 1}).quickfixtextfunc)
4939  " Add entries to the list when the quickfix buffer is hidden
4940  Xaddexpr ['F1:30:6:red']
4941  Xwindow
4942  call assert_equal('Line 30, Col 6', getline(3))
4943  Xclose
4944  call g:Xsetlist([], 'r', {'quickfixtextfunc' : ''})
4945  call assert_equal('', g:Xgetlist({'quickfixtextfunc' : 1}).quickfixtextfunc)
4946  set quickfixtextfunc&
4947  delfunc PerQfText
4948
4949  " Non-existing function
4950  set quickfixtextfunc=Tabc
4951  call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue']", 'E117:')
4952  call assert_fails("Xwindow", 'E117:')
4953  Xclose
4954  set quickfixtextfunc&
4955
4956  " set option to a non-function
4957  set quickfixtextfunc=[10,\ 20]
4958  call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue']", 'E117:')
4959  call assert_fails("Xwindow", 'E117:')
4960  Xclose
4961  set quickfixtextfunc&
4962
4963  " set option to a function with different set of arguments
4964  func Xqftext(a, b, c)
4965    return a:a .. a:b .. a:c
4966  endfunc
4967  set quickfixtextfunc=Xqftext
4968  call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue']", 'E119:')
4969  call assert_fails("Xwindow", 'E119:')
4970  Xclose
4971
4972  " set option to a function that returns a list with non-strings
4973  func Xqftext2(d)
4974    return ['one', [], 'two']
4975  endfunc
4976  set quickfixtextfunc=Xqftext2
4977  call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue', 'F1:30:6:red']",
4978                                                                  \ 'E730:')
4979  call assert_fails('Xwindow', 'E730:')
4980  call assert_equal(['one', 'F1|20 col 4| blue', 'F1|30 col 6| red'],
4981        \ getline(1, '$'))
4982  Xclose
4983
4984  set quickfixtextfunc&
4985  delfunc Xqftext
4986  delfunc Xqftext2
4987
4988  " set the global option to a lambda function
4989  set quickfixtextfunc={d\ ->\ map(g:Xgetlist({'id'\ :\ d.id,\ 'items'\ :\ 1}).items[d.start_idx-1:d.end_idx-1],\ 'v:val.text')}
4990  Xexpr ['F1:10:2:green', 'F1:20:4:blue']
4991  Xwindow
4992  call assert_equal(['green', 'blue'], getline(1, '$'))
4993  Xclose
4994  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)
4995  set quickfixtextfunc&
4996
4997  " use a lambda function that returns an empty list
4998  set quickfixtextfunc={d\ ->\ []}
4999  Xexpr ['F1:10:2:green', 'F1:20:4:blue']
5000  Xwindow
5001  call assert_equal(['F1|10 col 2| green', 'F1|20 col 4| blue'],
5002        \ getline(1, '$'))
5003  Xclose
5004  set quickfixtextfunc&
5005
5006  " use a lambda function that returns a list with empty strings
5007  set quickfixtextfunc={d\ ->\ ['',\ '']}
5008  Xexpr ['F1:10:2:green', 'F1:20:4:blue']
5009  Xwindow
5010  call assert_equal(['F1|10 col 2| green', 'F1|20 col 4| blue'],
5011        \ getline(1, '$'))
5012  Xclose
5013  set quickfixtextfunc&
5014
5015  " set the per-quickfix list text function to a lambda function
5016  call g:Xsetlist([], ' ',
5017        \ {'quickfixtextfunc' :
5018        \   {d -> map(g:Xgetlist({'id' : d.id, 'items' : 1}).items[d.start_idx-1:d.end_idx-1],
5019        \ "'Line ' .. v:val.lnum .. ', Col ' .. v:val.col")}})
5020  Xaddexpr ['F1:10:2:green', 'F1:20:4:blue']
5021  Xwindow
5022  call assert_equal('Line 10, Col 2', getline(1))
5023  call assert_equal('Line 20, Col 4', getline(2))
5024  Xclose
5025  call assert_match("function('<lambda>\\d\\+')", string(g:Xgetlist({'quickfixtextfunc' : 1}).quickfixtextfunc))
5026  call g:Xsetlist([], 'f')
5027endfunc
5028
5029func Test_qftextfunc()
5030  call Xtest_qftextfunc('c')
5031  call Xtest_qftextfunc('l')
5032endfunc
5033
5034" Running :lhelpgrep command more than once in a help window, doesn't jump to
5035" the help topic
5036func Test_lhelpgrep_from_help_window()
5037  call mkdir('Xtestdir/doc', 'p')
5038  call writefile(['window'], 'Xtestdir/doc/a.txt')
5039  call writefile(['buffer'], 'Xtestdir/doc/b.txt')
5040  let save_rtp = &rtp
5041  let &rtp = 'Xtestdir'
5042  lhelpgrep window
5043  lhelpgrep buffer
5044  call assert_equal('b.txt', fnamemodify(@%, ":p:t"))
5045  lhelpgrep window
5046  call assert_equal('a.txt', fnamemodify(@%, ":p:t"))
5047  let &rtp = save_rtp
5048  call delete('Xtestdir', 'rf')
5049  new | only!
5050endfunc
5051
5052" Test for the crash fixed by 7.3.715
5053func Test_setloclist_crash()
5054  %bw!
5055  let g:BufNum = bufnr()
5056  augroup QF_Test
5057    au!
5058    au BufUnload * call setloclist(0, [{'bufnr':g:BufNum, 'lnum':1, 'col':1, 'text': 'tango down'}])
5059  augroup END
5060
5061  try
5062    lvimgrep /.*/ *.mak
5063  catch /E926:/
5064  endtry
5065  call assert_equal('tango down', getloclist(0, {'items' : 0}).items[0].text)
5066  call assert_equal(1, getloclist(0, {'size' : 0}).size)
5067
5068  augroup QF_Test
5069    au!
5070  augroup END
5071  unlet g:BufNum
5072  %bw!
5073endfunc
5074
5075" vim: shiftwidth=2 sts=2 expandtab
5076