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('.') == 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('.') == 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
2836func Test_vimgrep_existing_swapfile()
2837  call writefile(['match apple with apple'], 'Xapple')
2838  call writefile(['swapfile'], '.Xapple.swp')
2839  let g:foundSwap = 0
2840  let g:ignoreSwapExists = 1
2841  augroup grep
2842    au SwapExists * let foundSwap = 1 | let v:swapchoice = 'e'
2843  augroup END
2844  vimgrep apple Xapple
2845  call assert_equal(1, g:foundSwap)
2846  call assert_match('.Xapple.swo', swapname(''))
2847
2848  call delete('Xapple')
2849  call delete('.Xapple.swp')
2850  augroup grep
2851    au! SwapExists
2852  augroup END
2853  unlet g:ignoreSwapExists
2854endfunc
2855
2856func XfreeTests(cchar)
2857  call s:setup_commands(a:cchar)
2858
2859  enew | only
2860
2861  " Deleting the quickfix stack should work even When the current list is
2862  " somewhere in the middle of the stack
2863  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2864  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2865  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2866  Xolder
2867  call g:Xsetlist([], 'f')
2868  call assert_equal(0, len(g:Xgetlist()))
2869
2870  " After deleting the stack, adding a new list should create a stack with a
2871  " single list.
2872  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2873  call assert_equal(1, g:Xgetlist({'all':1}).nr)
2874
2875  " Deleting the stack from a quickfix window should update/clear the
2876  " quickfix/location list window.
2877  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2878  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2879  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2880  Xolder
2881  Xwindow
2882  call g:Xsetlist([], 'f')
2883  call assert_equal(2, winnr('$'))
2884  call assert_equal(1, line('$'))
2885  Xclose
2886
2887  " Deleting the stack from a non-quickfix window should update/clear the
2888  " quickfix/location list window.
2889  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2890  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2891  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2892  Xolder
2893  Xwindow
2894  wincmd p
2895  call g:Xsetlist([], 'f')
2896  call assert_equal(0, len(g:Xgetlist()))
2897  wincmd p
2898  call assert_equal(2, winnr('$'))
2899  call assert_equal(1, line('$'))
2900
2901  " After deleting the location list stack, if the location list window is
2902  " opened, then a new location list should be created. So opening the
2903  " location list window again should not create a new window.
2904  if a:cchar == 'l'
2905      lexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2906      wincmd p
2907      lopen
2908      call assert_equal(2, winnr('$'))
2909  endif
2910  Xclose
2911endfunc
2912
2913" Tests for the quickfix free functionality
2914func Test_qf_free()
2915  call XfreeTests('c')
2916  call XfreeTests('l')
2917endfunc
2918
2919" Test for buffer overflow when parsing lines and adding new entries to
2920" the quickfix list.
2921func Test_bufoverflow()
2922  set efm=%f:%l:%m
2923  cgetexpr ['File1:100:' . repeat('x', 1025)]
2924
2925  set efm=%+GCompiler:\ %.%#,%f:%l:%m
2926  cgetexpr ['Compiler: ' . repeat('a', 1015), 'File1:10:Hello World']
2927
2928  set efm=%DEntering\ directory\ %f,%f:%l:%m
2929  cgetexpr ['Entering directory ' . repeat('a', 1006),
2930	      \ 'File1:10:Hello World']
2931  set efm&vim
2932endfunc
2933
2934" Tests for getting the quickfix stack size
2935func XsizeTests(cchar)
2936  call s:setup_commands(a:cchar)
2937
2938  call g:Xsetlist([], 'f')
2939  call assert_equal(0, g:Xgetlist({'nr':'$'}).nr)
2940  call assert_equal('', g:Xgetlist({'nr':'$', 'all':1}).title)
2941  call assert_equal(0, g:Xgetlist({'nr':0}).nr)
2942
2943  Xexpr "File1:10:Line1"
2944  Xexpr "File2:20:Line2"
2945  Xexpr "File3:30:Line3"
2946  Xolder | Xolder
2947  call assert_equal(3, g:Xgetlist({'nr':'$'}).nr)
2948  call g:Xsetlist([], 'f')
2949
2950  Xexpr "File1:10:Line1"
2951  Xexpr "File2:20:Line2"
2952  Xexpr "File3:30:Line3"
2953  Xolder | Xolder
2954  call g:Xsetlist([], 'a', {'nr':'$', 'title':'Compiler'})
2955  call assert_equal('Compiler', g:Xgetlist({'nr':3, 'all':1}).title)
2956endfunc
2957
2958func Test_Qf_Size()
2959  call XsizeTests('c')
2960  call XsizeTests('l')
2961endfunc
2962
2963func Test_cclose_from_copen()
2964    augroup QF_Test
2965	au!
2966        au FileType qf :call assert_fails(':cclose', 'E788')
2967    augroup END
2968    copen
2969    augroup QF_Test
2970	au!
2971    augroup END
2972    augroup! QF_Test
2973endfunc
2974
2975func Test_cclose_in_autocmd()
2976  " Problem is only triggered if "starting" is zero, so that the OptionsSet
2977  " event will be triggered.
2978  call test_override('starting', 1)
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
2988  call test_override('starting', 0)
2989endfunc
2990
2991" Check that ":file" without an argument is possible even when "curbuf_lock"
2992" is set.
2993func Test_file_from_copen()
2994  " Works without argument.
2995  augroup QF_Test
2996    au!
2997    au FileType qf file
2998  augroup END
2999  copen
3000
3001  augroup QF_Test
3002    au!
3003  augroup END
3004  cclose
3005
3006  " Fails with argument.
3007  augroup QF_Test
3008    au!
3009    au FileType qf call assert_fails(':file foo', 'E788')
3010  augroup END
3011  copen
3012  augroup QF_Test
3013    au!
3014  augroup END
3015  cclose
3016
3017  augroup! QF_Test
3018endfunc
3019
3020func Test_resize_from_copen()
3021  augroup QF_Test
3022    au!
3023    au FileType qf resize 5
3024  augroup END
3025  try
3026    " This should succeed without any exception.  No other buffers are
3027    " involved in the autocmd.
3028    copen
3029  finally
3030    augroup QF_Test
3031      au!
3032    augroup END
3033    augroup! QF_Test
3034  endtry
3035endfunc
3036
3037" Tests for the quickfix buffer b:changedtick variable
3038func Xchangedtick_tests(cchar)
3039  call s:setup_commands(a:cchar)
3040
3041  new | only
3042
3043  Xexpr "" | Xexpr "" | Xexpr ""
3044
3045  Xopen
3046  Xolder
3047  Xolder
3048  Xaddexpr "F1:10:Line10"
3049  Xaddexpr "F2:20:Line20"
3050  call g:Xsetlist([{"filename":"F3", "lnum":30, "text":"Line30"}], 'a')
3051  call g:Xsetlist([], 'f')
3052  call assert_equal(8, getbufvar('%', 'changedtick'))
3053  Xclose
3054endfunc
3055
3056func Test_changedtick()
3057  call Xchangedtick_tests('c')
3058  call Xchangedtick_tests('l')
3059endfunc
3060
3061" Tests for parsing an expression using setqflist()
3062func Xsetexpr_tests(cchar)
3063  call s:setup_commands(a:cchar)
3064
3065  let t = ["File1:10:Line10", "File1:20:Line20"]
3066  call g:Xsetlist([], ' ', {'lines' : t})
3067  call g:Xsetlist([], 'a', {'lines' : ["File1:30:Line30"]})
3068
3069  let l = g:Xgetlist()
3070  call assert_equal(3, len(l))
3071  call assert_equal(20, l[1].lnum)
3072  call assert_equal('Line30', l[2].text)
3073  call g:Xsetlist([], 'r', {'lines' : ["File2:5:Line5"]})
3074  let l = g:Xgetlist()
3075  call assert_equal(1, len(l))
3076  call assert_equal('Line5', l[0].text)
3077  call assert_equal(-1, g:Xsetlist([], 'a', {'lines' : 10}))
3078  call assert_equal(-1, g:Xsetlist([], 'a', {'lines' : "F1:10:L10"}))
3079
3080  call g:Xsetlist([], 'f')
3081  " Add entries to multiple lists
3082  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["File1:10:Line10"]})
3083  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["File2:20:Line20"]})
3084  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["File1:15:Line15"]})
3085  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["File2:25:Line25"]})
3086  call assert_equal('Line15', g:Xgetlist({'nr':1, 'items':1}).items[1].text)
3087  call assert_equal('Line25', g:Xgetlist({'nr':2, 'items':1}).items[1].text)
3088
3089  " Adding entries using a custom efm
3090  set efm&
3091  call g:Xsetlist([], ' ', {'efm' : '%f#%l#%m',
3092				\ 'lines' : ["F1#10#L10", "F2#20#L20"]})
3093  call assert_equal(20, g:Xgetlist({'items':1}).items[1].lnum)
3094  call g:Xsetlist([], 'a', {'efm' : '%f#%l#%m', 'lines' : ["F3:30:L30"]})
3095  call assert_equal('F3:30:L30', g:Xgetlist({'items':1}).items[2].text)
3096  call assert_equal(20, g:Xgetlist({'items':1}).items[1].lnum)
3097  call assert_equal(-1, g:Xsetlist([], 'a', {'efm' : [],
3098				\ 'lines' : ['F1:10:L10']}))
3099endfunc
3100
3101func Test_setexpr()
3102  call Xsetexpr_tests('c')
3103  call Xsetexpr_tests('l')
3104endfunc
3105
3106" Tests for per quickfix/location list directory stack
3107func Xmultidirstack_tests(cchar)
3108  call s:setup_commands(a:cchar)
3109
3110  call g:Xsetlist([], 'f')
3111  Xexpr "" | Xexpr ""
3112
3113  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["Entering dir 'Xone/a'"]})
3114  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["Entering dir 'Xtwo/a'"]})
3115  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["one.txt:3:one one one"]})
3116  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["two.txt:5:two two two"]})
3117
3118  let l1 = g:Xgetlist({'nr':1, 'items':1})
3119  let l2 = g:Xgetlist({'nr':2, 'items':1})
3120  call assert_equal('Xone/a/one.txt', bufname(l1.items[1].bufnr))
3121  call assert_equal(3, l1.items[1].lnum)
3122  call assert_equal('Xtwo/a/two.txt', bufname(l2.items[1].bufnr))
3123  call assert_equal(5, l2.items[1].lnum)
3124endfunc
3125
3126func Test_multidirstack()
3127  call mkdir('Xone/a', 'p')
3128  call mkdir('Xtwo/a', 'p')
3129  let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7']
3130  call writefile(lines, 'Xone/a/one.txt')
3131  call writefile(lines, 'Xtwo/a/two.txt')
3132  let save_efm = &efm
3133  set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f'
3134
3135  call Xmultidirstack_tests('c')
3136  call Xmultidirstack_tests('l')
3137
3138  let &efm = save_efm
3139  call delete('Xone', 'rf')
3140  call delete('Xtwo', 'rf')
3141endfunc
3142
3143" Tests for per quickfix/location list file stack
3144func Xmultifilestack_tests(cchar)
3145  call s:setup_commands(a:cchar)
3146
3147  call g:Xsetlist([], 'f')
3148  Xexpr "" | Xexpr ""
3149
3150  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["[one.txt]"]})
3151  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["[two.txt]"]})
3152  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["(3,5) one one one"]})
3153  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["(5,9) two two two"]})
3154
3155  let l1 = g:Xgetlist({'nr':1, 'items':1})
3156  let l2 = g:Xgetlist({'nr':2, 'items':1})
3157  call assert_equal('one.txt', bufname(l1.items[1].bufnr))
3158  call assert_equal(3, l1.items[1].lnum)
3159  call assert_equal('two.txt', bufname(l2.items[1].bufnr))
3160  call assert_equal(5, l2.items[1].lnum)
3161
3162  " Test for start of a new error line in the same line where a previous
3163  " error line ends with a file stack.
3164  let efm_val = 'Error\ l%l\ in\ %f,'
3165  let efm_val .= '%-P%>(%f%r,Error\ l%l\ in\ %m,%-Q)%r'
3166  let l = g:Xgetlist({'lines' : [
3167	      \ '(one.txt',
3168	      \ 'Error l4 in one.txt',
3169	      \ ') (two.txt',
3170	      \ 'Error l6 in two.txt',
3171	      \ ')',
3172	      \ 'Error l8 in one.txt'
3173	      \ ], 'efm' : efm_val})
3174  call assert_equal(3, len(l.items))
3175  call assert_equal('one.txt', bufname(l.items[0].bufnr))
3176  call assert_equal(4, l.items[0].lnum)
3177  call assert_equal('one.txt', l.items[0].text)
3178  call assert_equal('two.txt', bufname(l.items[1].bufnr))
3179  call assert_equal(6, l.items[1].lnum)
3180  call assert_equal('two.txt', l.items[1].text)
3181  call assert_equal('one.txt', bufname(l.items[2].bufnr))
3182  call assert_equal(8, l.items[2].lnum)
3183  call assert_equal('', l.items[2].text)
3184endfunc
3185
3186func Test_multifilestack()
3187  let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7']
3188  call writefile(lines, 'one.txt')
3189  call writefile(lines, 'two.txt')
3190  let save_efm = &efm
3191  set efm=%+P[%f],(%l\\,%c)\ %m,%-Q
3192
3193  call Xmultifilestack_tests('c')
3194  call Xmultifilestack_tests('l')
3195
3196  let &efm = save_efm
3197  call delete('one.txt')
3198  call delete('two.txt')
3199endfunc
3200
3201" Tests for per buffer 'efm' setting
3202func Test_perbuf_efm()
3203  call writefile(["File1-10-Line10"], 'one.txt')
3204  call writefile(["File2#20#Line20"], 'two.txt')
3205  set efm=%f#%l#%m
3206  new | only
3207  new
3208  setlocal efm=%f-%l-%m
3209  cfile one.txt
3210  wincmd w
3211  caddfile two.txt
3212
3213  let l = getqflist()
3214  call assert_equal(10, l[0].lnum)
3215  call assert_equal('Line20', l[1].text)
3216
3217  set efm&
3218  new | only
3219  call delete('one.txt')
3220  call delete('two.txt')
3221endfunc
3222
3223" Open multiple help windows using ":lhelpgrep
3224" This test used to crash Vim
3225func Test_Multi_LL_Help()
3226  new | only
3227  lhelpgrep window
3228  lopen
3229  e#
3230  lhelpgrep buffer
3231  call assert_equal(3, winnr('$'))
3232  call assert_true(len(getloclist(1)) != 0)
3233  call assert_true(len(getloclist(2)) != 0)
3234  new | only
3235endfunc
3236
3237" Tests for adding new quickfix lists using setqflist()
3238func XaddQf_tests(cchar)
3239  call s:setup_commands(a:cchar)
3240
3241  " Create a new list using ' ' for action
3242  call g:Xsetlist([], 'f')
3243  call g:Xsetlist([], ' ', {'title' : 'Test1'})
3244  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3245  call assert_equal(1, l.nr)
3246  call assert_equal('Test1', l.title)
3247
3248  " Create a new list using ' ' for action and '$' for 'nr'
3249  call g:Xsetlist([], 'f')
3250  call g:Xsetlist([], ' ', {'title' : 'Test2', 'nr' : '$'})
3251  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3252  call assert_equal(1, l.nr)
3253  call assert_equal('Test2', l.title)
3254
3255  " Create a new list using 'a' for action
3256  call g:Xsetlist([], 'f')
3257  call g:Xsetlist([], 'a', {'title' : 'Test3'})
3258  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3259  call assert_equal(1, l.nr)
3260  call assert_equal('Test3', l.title)
3261
3262  " Create a new list using 'a' for action and '$' for 'nr'
3263  call g:Xsetlist([], 'f')
3264  call g:Xsetlist([], 'a', {'title' : 'Test3', 'nr' : '$'})
3265  call g:Xsetlist([], 'a', {'title' : 'Test4'})
3266  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3267  call assert_equal(1, l.nr)
3268  call assert_equal('Test4', l.title)
3269
3270  " Adding a quickfix list should remove all the lists following the current
3271  " list.
3272  Xexpr "" | Xexpr "" | Xexpr ""
3273  silent! 10Xolder
3274  call g:Xsetlist([], ' ', {'title' : 'Test5'})
3275  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3276  call assert_equal(2, l.nr)
3277  call assert_equal('Test5', l.title)
3278
3279  " Add a quickfix list using '$' as the list number.
3280  let lastqf = g:Xgetlist({'nr':'$'}).nr
3281  silent! 99Xolder
3282  call g:Xsetlist([], ' ', {'nr' : '$', 'title' : 'Test6'})
3283  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3284  call assert_equal(lastqf + 1, l.nr)
3285  call assert_equal('Test6', l.title)
3286
3287  " Add a quickfix list using 'nr' set to one more than the quickfix
3288  " list size.
3289  let lastqf = g:Xgetlist({'nr':'$'}).nr
3290  silent! 99Xolder
3291  call g:Xsetlist([], ' ', {'nr' : lastqf + 1, 'title' : 'Test7'})
3292  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3293  call assert_equal(lastqf + 1, l.nr)
3294  call assert_equal('Test7', l.title)
3295
3296  " Add a quickfix list to a stack with 10 lists using 'nr' set to '$'
3297  exe repeat('Xexpr "" |', 9) . 'Xexpr ""'
3298  silent! 99Xolder
3299  call g:Xsetlist([], ' ', {'nr' : '$', 'title' : 'Test8'})
3300  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3301  call assert_equal(10, l.nr)
3302  call assert_equal('Test8', l.title)
3303
3304  " Add a quickfix list using 'nr' set to a value greater than 10
3305  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : 12, 'title' : 'Test9'}))
3306
3307  " Try adding a quickfix list with 'nr' set to a value greater than the
3308  " quickfix list size but less than 10.
3309  call g:Xsetlist([], 'f')
3310  Xexpr "" | Xexpr "" | Xexpr ""
3311  silent! 99Xolder
3312  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : 8, 'title' : 'Test10'}))
3313
3314  " Add a quickfix list using 'nr' set to a some string or list
3315  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : [1,2], 'title' : 'Test11'}))
3316endfunc
3317
3318func Test_add_qf()
3319  call XaddQf_tests('c')
3320  call XaddQf_tests('l')
3321endfunc
3322
3323" Test for getting the quickfix list items from some text without modifying
3324" the quickfix stack
3325func XgetListFromLines(cchar)
3326  call s:setup_commands(a:cchar)
3327  call g:Xsetlist([], 'f')
3328
3329  let l = g:Xgetlist({'lines' : ["File2:20:Line20", "File2:30:Line30"]}).items
3330  call assert_equal(2, len(l))
3331  call assert_equal(30, l[1].lnum)
3332
3333  call assert_equal({}, g:Xgetlist({'lines' : 10}))
3334  call assert_equal({}, g:Xgetlist({'lines' : 'File1:10:Line10'}))
3335  call assert_equal([], g:Xgetlist({'lines' : []}).items)
3336  call assert_equal([], g:Xgetlist({'lines' : [10, 20]}).items)
3337
3338  " Parse text using a custom efm
3339  set efm&
3340  let l = g:Xgetlist({'lines':['File3#30#Line30'], 'efm' : '%f#%l#%m'}).items
3341  call assert_equal('Line30', l[0].text)
3342  let l = g:Xgetlist({'lines':['File3:30:Line30'], 'efm' : '%f-%l-%m'}).items
3343  call assert_equal('File3:30:Line30', l[0].text)
3344  let l = g:Xgetlist({'lines':['File3:30:Line30'], 'efm' : [1,2]})
3345  call assert_equal({}, l)
3346  call assert_fails("call g:Xgetlist({'lines':['abc'], 'efm':'%2'})", 'E376:')
3347  call assert_fails("call g:Xgetlist({'lines':['abc'], 'efm':''})", 'E378:')
3348
3349  " Make sure that the quickfix stack is not modified
3350  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
3351endfunc
3352
3353func Test_get_list_from_lines()
3354  call XgetListFromLines('c')
3355  call XgetListFromLines('l')
3356endfunc
3357
3358" Tests for the quickfix list id
3359func Xqfid_tests(cchar)
3360  call s:setup_commands(a:cchar)
3361
3362  call g:Xsetlist([], 'f')
3363  call assert_equal(0, g:Xgetlist({'id':0}).id)
3364  Xexpr ''
3365  let start_id = g:Xgetlist({'id' : 0}).id
3366  Xexpr '' | Xexpr ''
3367  Xolder
3368  call assert_equal(start_id, g:Xgetlist({'id':0, 'nr':1}).id)
3369  call assert_equal(start_id + 1, g:Xgetlist({'id':0, 'nr':0}).id)
3370  call assert_equal(start_id + 2, g:Xgetlist({'id':0, 'nr':'$'}).id)
3371  call assert_equal(0, g:Xgetlist({'id':0, 'nr':99}).id)
3372  call assert_equal(2, g:Xgetlist({'id':start_id + 1, 'nr':0}).nr)
3373  call assert_equal(0, g:Xgetlist({'id':99, 'nr':0}).id)
3374  call assert_equal(0, g:Xgetlist({'id':"abc", 'nr':0}).id)
3375
3376  call g:Xsetlist([], 'a', {'id':start_id, 'context':[1,2]})
3377  call assert_equal([1,2], g:Xgetlist({'nr':1, 'context':1}).context)
3378  call g:Xsetlist([], 'a', {'id':start_id+1, 'lines':['F1:10:L10']})
3379  call assert_equal('L10', g:Xgetlist({'nr':2, 'items':1}).items[0].text)
3380  call assert_equal(-1, g:Xsetlist([], 'a', {'id':999, 'title':'Vim'}))
3381  call assert_equal(-1, g:Xsetlist([], 'a', {'id':'abc', 'title':'Vim'}))
3382
3383  let qfid = g:Xgetlist({'id':0, 'nr':0})
3384  call g:Xsetlist([], 'f')
3385  call assert_equal(0, g:Xgetlist({'id':qfid, 'nr':0}).id)
3386endfunc
3387
3388func Test_qf_id()
3389  call Xqfid_tests('c')
3390  call Xqfid_tests('l')
3391endfunc
3392
3393func Xqfjump_tests(cchar)
3394  call s:setup_commands(a:cchar)
3395
3396  call writefile(["Line1\tFoo", "Line2"], 'F1')
3397  call writefile(["Line1\tBar", "Line2"], 'F2')
3398  call writefile(["Line1\tBaz", "Line2"], 'F3')
3399
3400  call g:Xsetlist([], 'f')
3401
3402  " Tests for
3403  "   Jumping to a line using a pattern
3404  "   Jumping to a column greater than the last column in a line
3405  "   Jumping to a line greater than the last line in the file
3406  let l = []
3407  for i in range(1, 7)
3408    call add(l, {})
3409  endfor
3410  let l[0].filename='F1'
3411  let l[0].pattern='Line1'
3412  let l[1].filename='F2'
3413  let l[1].pattern='Line1'
3414  let l[2].filename='F3'
3415  let l[2].pattern='Line1'
3416  let l[3].filename='F3'
3417  let l[3].lnum=1
3418  let l[3].col=9
3419  let l[3].vcol=1
3420  let l[4].filename='F3'
3421  let l[4].lnum=99
3422  let l[5].filename='F3'
3423  let l[5].lnum=1
3424  let l[5].col=99
3425  let l[5].vcol=1
3426  let l[6].filename='F3'
3427  let l[6].pattern='abcxyz'
3428
3429  call g:Xsetlist([], ' ', {'items' : l})
3430  Xopen | only
3431  2Xnext
3432  call assert_equal(3, g:Xgetlist({'idx' : 0}).idx)
3433  call assert_equal('F3', @%)
3434  Xnext
3435  call assert_equal(7, col('.'))
3436  Xnext
3437  call assert_equal(2, line('.'))
3438  Xnext
3439  call assert_equal(9, col('.'))
3440  2
3441  Xnext
3442  call assert_equal(2, line('.'))
3443
3444  if a:cchar == 'l'
3445    " When jumping to a location list entry in the location list window and
3446    " no usable windows are available, then a new window should be opened.
3447    enew! | new | only
3448    call g:Xsetlist([], 'f')
3449    setlocal buftype=nofile
3450    new
3451    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']})
3452    Xopen
3453    let winid = win_getid()
3454    wincmd p
3455    close
3456    call win_gotoid(winid)
3457    Xnext
3458    call assert_equal(3, winnr('$'))
3459    call assert_equal(1, winnr())
3460    call assert_equal(2, line('.'))
3461
3462    " When jumping to an entry in the location list window and the window
3463    " associated with the location list is not present and a window containing
3464    " the file is already present, then that window should be used.
3465    close
3466    belowright new
3467    call g:Xsetlist([], 'f')
3468    edit F3
3469    call win_gotoid(winid)
3470    Xlast
3471    call assert_equal(3, winnr())
3472    call assert_equal(6, g:Xgetlist({'size' : 1}).size)
3473    call assert_equal(winid, g:Xgetlist({'winid' : 1}).winid)
3474  endif
3475
3476  " Cleanup
3477  enew!
3478  new | only
3479
3480  call delete('F1')
3481  call delete('F2')
3482  call delete('F3')
3483endfunc
3484
3485func Test_qfjump()
3486  call Xqfjump_tests('c')
3487  call Xqfjump_tests('l')
3488endfunc
3489
3490" Tests for the getqflist() and getloclist() functions when the list is not
3491" present or is empty
3492func Xgetlist_empty_tests(cchar)
3493  call s:setup_commands(a:cchar)
3494
3495  " Empty quickfix stack
3496  call g:Xsetlist([], 'f')
3497  call assert_equal('', g:Xgetlist({'context' : 0}).context)
3498  call assert_equal(0, g:Xgetlist({'id' : 0}).id)
3499  call assert_equal(0, g:Xgetlist({'idx' : 0}).idx)
3500  call assert_equal([], g:Xgetlist({'items' : 0}).items)
3501  call assert_equal(0, g:Xgetlist({'nr' : 0}).nr)
3502  call assert_equal(0, g:Xgetlist({'size' : 0}).size)
3503  call assert_equal('', g:Xgetlist({'title' : 0}).title)
3504  call assert_equal(0, g:Xgetlist({'winid' : 0}).winid)
3505  call assert_equal(0, g:Xgetlist({'changedtick' : 0}).changedtick)
3506  if a:cchar == 'c'
3507    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0,
3508		  \ 'items' : [], 'nr' : 0, 'size' : 0, 'qfbufnr' : 0,
3509		  \ 'title' : '', 'winid' : 0, 'changedtick': 0,
3510                  \ 'quickfixtextfunc' : ''}, g:Xgetlist({'all' : 0}))
3511  else
3512    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0,
3513		\ 'items' : [], 'nr' : 0, 'size' : 0, 'title' : '',
3514		\ 'winid' : 0, 'changedtick': 0, 'filewinid' : 0,
3515		\ 'qfbufnr' : 0, 'quickfixtextfunc' : ''},
3516		\ g:Xgetlist({'all' : 0}))
3517  endif
3518
3519  " Quickfix window with empty stack
3520  silent! Xopen
3521  let qfwinid = (a:cchar == 'c') ? win_getid() : 0
3522  let qfbufnr = (a:cchar == 'c') ? bufnr('') : 0
3523  call assert_equal(qfwinid, g:Xgetlist({'winid' : 0}).winid)
3524  Xclose
3525
3526  " Empty quickfix list
3527  Xexpr ""
3528  call assert_equal('', g:Xgetlist({'context' : 0}).context)
3529  call assert_notequal(0, g:Xgetlist({'id' : 0}).id)
3530  call assert_equal(0, g:Xgetlist({'idx' : 0}).idx)
3531  call assert_equal([], g:Xgetlist({'items' : 0}).items)
3532  call assert_notequal(0, g:Xgetlist({'nr' : 0}).nr)
3533  call assert_equal(0, g:Xgetlist({'size' : 0}).size)
3534  call assert_notequal('', g:Xgetlist({'title' : 0}).title)
3535  call assert_equal(0, g:Xgetlist({'winid' : 0}).winid)
3536  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3537
3538  let qfid = g:Xgetlist({'id' : 0}).id
3539  call g:Xsetlist([], 'f')
3540
3541  " Non-existing quickfix identifier
3542  call assert_equal('', g:Xgetlist({'id' : qfid, 'context' : 0}).context)
3543  call assert_equal(0, g:Xgetlist({'id' : qfid}).id)
3544  call assert_equal(0, g:Xgetlist({'id' : qfid, 'idx' : 0}).idx)
3545  call assert_equal([], g:Xgetlist({'id' : qfid, 'items' : 0}).items)
3546  call assert_equal(0, g:Xgetlist({'id' : qfid, 'nr' : 0}).nr)
3547  call assert_equal(0, g:Xgetlist({'id' : qfid, 'size' : 0}).size)
3548  call assert_equal('', g:Xgetlist({'id' : qfid, 'title' : 0}).title)
3549  call assert_equal(0, g:Xgetlist({'id' : qfid, 'winid' : 0}).winid)
3550  call assert_equal(0, g:Xgetlist({'id' : qfid, 'changedtick' : 0}).changedtick)
3551  if a:cchar == 'c'
3552    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
3553		\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
3554		\ 'qfbufnr' : qfbufnr, 'quickfixtextfunc' : '',
3555		\ 'changedtick' : 0}, g:Xgetlist({'id' : qfid, 'all' : 0}))
3556  else
3557    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
3558		\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
3559		\ 'changedtick' : 0, 'filewinid' : 0, 'qfbufnr' : 0,
3560                \ 'quickfixtextfunc' : ''},
3561		\ g:Xgetlist({'id' : qfid, 'all' : 0}))
3562  endif
3563
3564  " Non-existing quickfix list number
3565  call assert_equal('', g:Xgetlist({'nr' : 5, 'context' : 0}).context)
3566  call assert_equal(0, g:Xgetlist({'nr' : 5}).nr)
3567  call assert_equal(0, g:Xgetlist({'nr' : 5, 'idx' : 0}).idx)
3568  call assert_equal([], g:Xgetlist({'nr' : 5, 'items' : 0}).items)
3569  call assert_equal(0, g:Xgetlist({'nr' : 5, 'id' : 0}).id)
3570  call assert_equal(0, g:Xgetlist({'nr' : 5, 'size' : 0}).size)
3571  call assert_equal('', g:Xgetlist({'nr' : 5, 'title' : 0}).title)
3572  call assert_equal(0, g:Xgetlist({'nr' : 5, 'winid' : 0}).winid)
3573  call assert_equal(0, g:Xgetlist({'nr' : 5, 'changedtick' : 0}).changedtick)
3574  if a:cchar == 'c'
3575    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
3576		\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
3577		\ 'changedtick' : 0, 'qfbufnr' : qfbufnr,
3578                \ 'quickfixtextfunc' : ''}, g:Xgetlist({'nr' : 5, 'all' : 0}))
3579  else
3580    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
3581		\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
3582		\ 'changedtick' : 0, 'filewinid' : 0, 'qfbufnr' : 0,
3583                \ 'quickfixtextfunc' : ''}, g:Xgetlist({'nr' : 5, 'all' : 0}))
3584  endif
3585endfunc
3586
3587func Test_getqflist()
3588  call Xgetlist_empty_tests('c')
3589  call Xgetlist_empty_tests('l')
3590endfunc
3591
3592func Test_getqflist_invalid_nr()
3593  " The following commands used to crash Vim
3594  cexpr ""
3595  call getqflist({'nr' : $XXX_DOES_NOT_EXIST_XXX})
3596
3597  " Cleanup
3598  call setqflist([], 'r')
3599endfunc
3600
3601" Tests for the quickfix/location list changedtick
3602func Xqftick_tests(cchar)
3603  call s:setup_commands(a:cchar)
3604
3605  call g:Xsetlist([], 'f')
3606
3607  Xexpr "F1:10:Line10"
3608  let qfid = g:Xgetlist({'id' : 0}).id
3609  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3610  Xaddexpr "F2:20:Line20\nF2:21:Line21"
3611  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
3612  call g:Xsetlist([], 'a', {'lines' : ["F3:30:Line30", "F3:31:Line31"]})
3613  call assert_equal(3, g:Xgetlist({'changedtick' : 0}).changedtick)
3614  call g:Xsetlist([], 'r', {'lines' : ["F4:40:Line40"]})
3615  call assert_equal(4, g:Xgetlist({'changedtick' : 0}).changedtick)
3616  call g:Xsetlist([], 'a', {'title' : 'New Title'})
3617  call assert_equal(5, g:Xgetlist({'changedtick' : 0}).changedtick)
3618
3619  enew!
3620  call append(0, ["F5:50:L50", "F6:60:L60"])
3621  Xaddbuffer
3622  call assert_equal(6, g:Xgetlist({'changedtick' : 0}).changedtick)
3623  enew!
3624
3625  call g:Xsetlist([], 'a', {'context' : {'bus' : 'pci'}})
3626  call assert_equal(7, g:Xgetlist({'changedtick' : 0}).changedtick)
3627  call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'},
3628	      \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], 'a')
3629  call assert_equal(8, g:Xgetlist({'changedtick' : 0}).changedtick)
3630  call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'},
3631	      \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], ' ')
3632  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3633  call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'},
3634	      \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], 'r')
3635  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
3636
3637  call writefile(["F8:80:L80", "F8:81:L81"], "Xone")
3638  Xfile Xone
3639  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3640  Xaddfile Xone
3641  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
3642
3643  " Test case for updating a non-current quickfix list
3644  call g:Xsetlist([], 'f')
3645  Xexpr "F1:1:L1"
3646  Xexpr "F2:2:L2"
3647  call g:Xsetlist([], 'a', {'nr' : 1, "lines" : ["F10:10:L10"]})
3648  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3649  call assert_equal(2, g:Xgetlist({'nr' : 1, 'changedtick' : 0}).changedtick)
3650
3651  call delete("Xone")
3652endfunc
3653
3654func Test_qf_tick()
3655  call Xqftick_tests('c')
3656  call Xqftick_tests('l')
3657endfunc
3658
3659" Test helpgrep with lang specifier
3660func Xtest_helpgrep_with_lang_specifier(cchar)
3661  call s:setup_commands(a:cchar)
3662  Xhelpgrep Vim@en
3663  call assert_equal('help', &filetype)
3664  call assert_notequal(0, g:Xgetlist({'nr' : '$'}).nr)
3665  new | only
3666endfunc
3667
3668func Test_helpgrep_with_lang_specifier()
3669  call Xtest_helpgrep_with_lang_specifier('c')
3670  call Xtest_helpgrep_with_lang_specifier('l')
3671endfunc
3672
3673" The following test used to crash Vim.
3674" Open the location list window and close the regular window associated with
3675" the location list. When the garbage collection runs now, it incorrectly
3676" marks the location list context as not in use and frees the context.
3677func Test_ll_window_ctx()
3678  call setloclist(0, [], 'f')
3679  call setloclist(0, [], 'a', {'context' : []})
3680  lopen | only
3681  call test_garbagecollect_now()
3682  echo getloclist(0, {'context' : 1}).context
3683  enew | only
3684endfunc
3685
3686" The following test used to crash vim
3687func Test_lfile_crash()
3688  sp Xtest
3689  au QuickFixCmdPre * bw
3690  call assert_fails('lfile', 'E40')
3691  au! QuickFixCmdPre
3692endfunc
3693
3694" The following test used to crash vim
3695func Test_lbuffer_crash()
3696  sv Xtest
3697  augroup QF_Test
3698    au!
3699    au * * bw
3700  augroup END
3701  lbuffer
3702  augroup QF_Test
3703    au!
3704  augroup END
3705endfunc
3706
3707" The following test used to crash vim
3708func Test_lexpr_crash()
3709  augroup QF_Test
3710    au!
3711    au * * call setloclist(0, [], 'f')
3712  augroup END
3713  lexpr ""
3714  augroup QF_Test
3715    au!
3716  augroup END
3717
3718  enew | only
3719  augroup QF_Test
3720    au!
3721    au BufNew * call setloclist(0, [], 'f')
3722  augroup END
3723  lexpr 'x:1:x'
3724  augroup QF_Test
3725    au!
3726  augroup END
3727
3728  enew | only
3729  lexpr ''
3730  lopen
3731  augroup QF_Test
3732    au!
3733    au FileType * call setloclist(0, [], 'f')
3734  augroup END
3735  lexpr ''
3736  augroup QF_Test
3737    au!
3738  augroup END
3739endfunc
3740
3741" The following test used to crash Vim
3742func Test_lvimgrep_crash()
3743  sv Xtest
3744  augroup QF_Test
3745    au!
3746    au * * call setloclist(0, [], 'f')
3747  augroup END
3748  lvimgrep quickfix test_quickfix.vim
3749  augroup QF_Test
3750    au!
3751  augroup END
3752
3753  new | only
3754  augroup QF_Test
3755    au!
3756    au BufEnter * call setloclist(0, [], 'r')
3757  augroup END
3758  call assert_fails('lvimgrep Test_lvimgrep_crash *', 'E926:')
3759  augroup QF_Test
3760    au!
3761  augroup END
3762
3763  enew | only
3764endfunc
3765
3766func Test_lvimgrep_crash2()
3767  au BufNewFile x sfind
3768  call assert_fails('lvimgrep x x', 'E471:')
3769  call assert_fails('lvimgrep x x x', 'E471:')
3770
3771  au! BufNewFile
3772endfunc
3773
3774" Test for the position of the quickfix and location list window
3775func Test_qfwin_pos()
3776  " Open two windows
3777  new | only
3778  new
3779  cexpr ['F1:10:L10']
3780  copen
3781  " Quickfix window should be the bottom most window
3782  call assert_equal(3, winnr())
3783  close
3784  " Open at the very top
3785  wincmd t
3786  topleft copen
3787  call assert_equal(1, winnr())
3788  close
3789  " open left of the current window
3790  wincmd t
3791  below new
3792  leftabove copen
3793  call assert_equal(2, winnr())
3794  close
3795  " open right of the current window
3796  rightbelow copen
3797  call assert_equal(3, winnr())
3798  close
3799endfunc
3800
3801" Tests for quickfix/location lists changed by autocommands when
3802" :vimgrep/:lvimgrep commands are running.
3803func Test_vimgrep_autocmd()
3804  call setqflist([], 'f')
3805  call writefile(['stars'], 'Xtest1.txt')
3806  call writefile(['stars'], 'Xtest2.txt')
3807
3808  " Test 1:
3809  " When searching for a pattern using :vimgrep, if the quickfix list is
3810  " changed by an autocmd, the results should be added to the correct quickfix
3811  " list.
3812  autocmd BufRead Xtest2.txt cexpr '' | cexpr ''
3813  silent vimgrep stars Xtest*.txt
3814  call assert_equal(1, getqflist({'nr' : 0}).nr)
3815  call assert_equal(3, getqflist({'nr' : '$'}).nr)
3816  call assert_equal('Xtest2.txt', bufname(getqflist()[1].bufnr))
3817  au! BufRead Xtest2.txt
3818
3819  " Test 2:
3820  " When searching for a pattern using :vimgrep, if the quickfix list is
3821  " freed, then a error should be given.
3822  silent! %bwipe!
3823  call setqflist([], 'f')
3824  autocmd BufRead Xtest2.txt for i in range(10) | cexpr '' | endfor
3825  call assert_fails('vimgrep stars Xtest*.txt', 'E925:')
3826  au! BufRead Xtest2.txt
3827
3828  " Test 3:
3829  " When searching for a pattern using :lvimgrep, if the location list is
3830  " freed, then the command should error out.
3831  silent! %bwipe!
3832  let g:save_winid = win_getid()
3833  autocmd BufRead Xtest2.txt call setloclist(g:save_winid, [], 'f')
3834  call assert_fails('lvimgrep stars Xtest*.txt', 'E926:')
3835  au! BufRead Xtest2.txt
3836
3837  call delete('Xtest1.txt')
3838  call delete('Xtest2.txt')
3839  call setqflist([], 'f')
3840endfunc
3841
3842" Test for an autocmd changing the current directory when running vimgrep
3843func Xvimgrep_autocmd_cd(cchar)
3844  call s:setup_commands(a:cchar)
3845
3846  %bwipe
3847  let save_cwd = getcwd()
3848
3849  augroup QF_Test
3850    au!
3851    autocmd BufRead * silent cd %:p:h
3852  augroup END
3853
3854  10Xvimgrep /vim/ Xdir/**
3855  let l = g:Xgetlist()
3856  call assert_equal('f1.txt', bufname(l[0].bufnr))
3857  call assert_equal('f2.txt', fnamemodify(bufname(l[2].bufnr), ':t'))
3858
3859  augroup QF_Test
3860    au!
3861  augroup END
3862
3863  exe 'cd ' . save_cwd
3864endfunc
3865
3866func Test_vimgrep_autocmd_cd()
3867  call mkdir('Xdir/a', 'p')
3868  call mkdir('Xdir/b', 'p')
3869  call writefile(['a_L1_vim', 'a_L2_vim'], 'Xdir/a/f1.txt')
3870  call writefile(['b_L1_vim', 'b_L2_vim'], 'Xdir/b/f2.txt')
3871  call Xvimgrep_autocmd_cd('c')
3872  call Xvimgrep_autocmd_cd('l')
3873  %bwipe
3874  call delete('Xdir', 'rf')
3875endfunc
3876
3877" The following test used to crash Vim
3878func Test_lhelpgrep_autocmd()
3879  lhelpgrep quickfix
3880  autocmd QuickFixCmdPost * call setloclist(0, [], 'f')
3881  lhelpgrep buffer
3882  call assert_equal('help', &filetype)
3883  call assert_equal(0, getloclist(0, {'nr' : '$'}).nr)
3884  lhelpgrep tabpage
3885  call assert_equal('help', &filetype)
3886  call assert_equal(1, getloclist(0, {'nr' : '$'}).nr)
3887  au! QuickFixCmdPost
3888
3889  new | only
3890  augroup QF_Test
3891    au!
3892    au BufEnter * call setqflist([], 'f')
3893  augroup END
3894  call assert_fails('helpgrep quickfix', 'E925:')
3895  augroup QF_Test
3896    au! BufEnter
3897  augroup END
3898
3899  new | only
3900  augroup QF_Test
3901    au!
3902    au BufEnter * call setqflist([], 'r')
3903  augroup END
3904  call assert_fails('helpgrep quickfix', 'E925:')
3905  augroup QF_Test
3906    au! BufEnter
3907  augroup END
3908
3909  new | only
3910  augroup QF_Test
3911    au!
3912    au BufEnter * call setloclist(0, [], 'r')
3913  augroup END
3914  call assert_fails('lhelpgrep quickfix', 'E926:')
3915  augroup QF_Test
3916    au! BufEnter
3917  augroup END
3918
3919  new | only
3920endfunc
3921
3922" Test for shortening/simplifying the file name when opening the
3923" quickfix window or when displaying the quickfix list
3924func Test_shorten_fname()
3925  CheckUnix
3926  %bwipe
3927  " Create a quickfix list with a absolute path filename
3928  let fname = getcwd() . '/test_quickfix.vim'
3929  call setqflist([], ' ', {'lines':[fname . ":20:Line20"], 'efm':'%f:%l:%m'})
3930  call assert_equal(fname, bufname('test_quickfix.vim'))
3931  " Opening the quickfix window should simplify the file path
3932  cwindow
3933  call assert_equal('test_quickfix.vim', bufname('test_quickfix.vim'))
3934  cclose
3935  %bwipe
3936  " Create a quickfix list with a absolute path filename
3937  call setqflist([], ' ', {'lines':[fname . ":20:Line20"], 'efm':'%f:%l:%m'})
3938  call assert_equal(fname, bufname('test_quickfix.vim'))
3939  " Displaying the quickfix list should simplify the file path
3940  silent! clist
3941  call assert_equal('test_quickfix.vim', bufname('test_quickfix.vim'))
3942endfunc
3943
3944" Quickfix title tests
3945" In the below tests, 'exe "cmd"' is used to invoke the quickfix commands.
3946" Otherwise due to indentation, the title is set with spaces at the beginning
3947" of the command.
3948func Test_qftitle()
3949  call writefile(["F1:1:Line1"], 'Xerr')
3950
3951  " :cexpr
3952  exe "cexpr readfile('Xerr')"
3953  call assert_equal(":cexpr readfile('Xerr')", getqflist({'title' : 1}).title)
3954
3955  " :cgetexpr
3956  exe "cgetexpr readfile('Xerr')"
3957  call assert_equal(":cgetexpr readfile('Xerr')",
3958					\ getqflist({'title' : 1}).title)
3959
3960  " :caddexpr
3961  call setqflist([], 'f')
3962  exe "caddexpr readfile('Xerr')"
3963  call assert_equal(":caddexpr readfile('Xerr')",
3964					\ getqflist({'title' : 1}).title)
3965
3966  " :cbuffer
3967  new Xerr
3968  exe "cbuffer"
3969  call assert_equal(':cbuffer (Xerr)', getqflist({'title' : 1}).title)
3970
3971  " :cgetbuffer
3972  edit Xerr
3973  exe "cgetbuffer"
3974  call assert_equal(':cgetbuffer (Xerr)', getqflist({'title' : 1}).title)
3975
3976  " :caddbuffer
3977  call setqflist([], 'f')
3978  edit Xerr
3979  exe "caddbuffer"
3980  call assert_equal(':caddbuffer (Xerr)', getqflist({'title' : 1}).title)
3981
3982  " :cfile
3983  exe "cfile Xerr"
3984  call assert_equal(':cfile Xerr', getqflist({'title' : 1}).title)
3985
3986  " :cgetfile
3987  exe "cgetfile Xerr"
3988  call assert_equal(':cgetfile Xerr', getqflist({'title' : 1}).title)
3989
3990  " :caddfile
3991  call setqflist([], 'f')
3992  exe "caddfile Xerr"
3993  call assert_equal(':caddfile Xerr', getqflist({'title' : 1}).title)
3994
3995  " :grep
3996  set grepprg=internal
3997  exe "grep F1 Xerr"
3998  call assert_equal(':grep F1 Xerr', getqflist({'title' : 1}).title)
3999
4000  " :grepadd
4001  call setqflist([], 'f')
4002  exe "grepadd F1 Xerr"
4003  call assert_equal(':grepadd F1 Xerr', getqflist({'title' : 1}).title)
4004  set grepprg&vim
4005
4006  " :vimgrep
4007  exe "vimgrep F1 Xerr"
4008  call assert_equal(':vimgrep F1 Xerr', getqflist({'title' : 1}).title)
4009
4010  " :vimgrepadd
4011  call setqflist([], 'f')
4012  exe "vimgrepadd F1 Xerr"
4013  call assert_equal(':vimgrepadd F1 Xerr', getqflist({'title' : 1}).title)
4014
4015  call setqflist(['F1:10:L10'], ' ')
4016  call assert_equal(':setqflist()', getqflist({'title' : 1}).title)
4017
4018  call setqflist([], 'f')
4019  call setqflist(['F1:10:L10'], 'a')
4020  call assert_equal(':setqflist()', getqflist({'title' : 1}).title)
4021
4022  call setqflist([], 'f')
4023  call setqflist(['F1:10:L10'], 'r')
4024  call assert_equal(':setqflist()', getqflist({'title' : 1}).title)
4025
4026  close
4027  call delete('Xerr')
4028
4029  call setqflist([], ' ', {'title' : 'Errors'})
4030  copen
4031  call assert_equal('Errors', w:quickfix_title)
4032  call setqflist([], 'r', {'items' : [{'filename' : 'a.c', 'lnum' : 10}]})
4033  call assert_equal('Errors', w:quickfix_title)
4034  cclose
4035endfunc
4036
4037func Test_lbuffer_with_bwipe()
4038  new
4039  new
4040  augroup nasty
4041    au * * bwipe
4042  augroup END
4043  lbuffer
4044  augroup nasty
4045    au!
4046  augroup END
4047endfunc
4048
4049" Test for an autocmd freeing the quickfix/location list when cexpr/lexpr is
4050" running
4051func Xexpr_acmd_freelist(cchar)
4052  call s:setup_commands(a:cchar)
4053
4054  " This was using freed memory.
4055  augroup nasty
4056    au * * call g:Xsetlist([], 'f')
4057  augroup END
4058  Xexpr "x"
4059  augroup nasty
4060    au!
4061  augroup END
4062endfunc
4063
4064func Test_cexpr_acmd_freelist()
4065  call Xexpr_acmd_freelist('c')
4066  call Xexpr_acmd_freelist('l')
4067endfunc
4068
4069" Test for commands that create a new quickfix/location list and jump to the
4070" first error automatically.
4071func Xjumpto_first_error_test(cchar)
4072  call s:setup_commands(a:cchar)
4073
4074  call s:create_test_file('Xtestfile1')
4075  call s:create_test_file('Xtestfile2')
4076  let l = ['Xtestfile1:2:Line2', 'Xtestfile2:4:Line4']
4077
4078  " Test for cexpr/lexpr
4079  enew
4080  Xexpr l
4081  call assert_equal('Xtestfile1', @%)
4082  call assert_equal(2, line('.'))
4083
4084  " Test for cfile/lfile
4085  enew
4086  call writefile(l, 'Xerr')
4087  Xfile Xerr
4088  call assert_equal('Xtestfile1', @%)
4089  call assert_equal(2, line('.'))
4090
4091  " Test for cbuffer/lbuffer
4092  edit Xerr
4093  Xbuffer
4094  call assert_equal('Xtestfile1', @%)
4095  call assert_equal(2, line('.'))
4096
4097  call delete('Xerr')
4098  call delete('Xtestfile1')
4099  call delete('Xtestfile2')
4100endfunc
4101
4102func Test_jumpto_first_error()
4103  call Xjumpto_first_error_test('c')
4104  call Xjumpto_first_error_test('l')
4105endfunc
4106
4107" Test for a quickfix autocmd changing the quickfix/location list before
4108" jumping to the first error in the new list.
4109func Xautocmd_changelist(cchar)
4110  call s:setup_commands(a:cchar)
4111
4112  " Test for cfile/lfile
4113  call s:create_test_file('Xtestfile1')
4114  call s:create_test_file('Xtestfile2')
4115  Xexpr 'Xtestfile1:2:Line2'
4116  autocmd QuickFixCmdPost * Xolder
4117  call writefile(['Xtestfile2:4:Line4'], 'Xerr')
4118  Xfile Xerr
4119  call assert_equal('Xtestfile2', @%)
4120  call assert_equal(4, line('.'))
4121  autocmd! QuickFixCmdPost
4122
4123  " Test for cbuffer/lbuffer
4124  call g:Xsetlist([], 'f')
4125  Xexpr 'Xtestfile1:2:Line2'
4126  autocmd QuickFixCmdPost * Xolder
4127  call writefile(['Xtestfile2:4:Line4'], 'Xerr')
4128  edit Xerr
4129  Xbuffer
4130  call assert_equal('Xtestfile2', @%)
4131  call assert_equal(4, line('.'))
4132  autocmd! QuickFixCmdPost
4133
4134  " Test for cexpr/lexpr
4135  call g:Xsetlist([], 'f')
4136  Xexpr 'Xtestfile1:2:Line2'
4137  autocmd QuickFixCmdPost * Xolder
4138  Xexpr 'Xtestfile2:4:Line4'
4139  call assert_equal('Xtestfile2', @%)
4140  call assert_equal(4, line('.'))
4141  autocmd! QuickFixCmdPost
4142
4143  " The grepprg may not be set on non-Unix systems
4144  if has('unix')
4145    " Test for grep/lgrep
4146    call g:Xsetlist([], 'f')
4147    Xexpr 'Xtestfile1:2:Line2'
4148    autocmd QuickFixCmdPost * Xolder
4149    silent Xgrep Line5 Xtestfile2
4150    call assert_equal('Xtestfile2', @%)
4151    call assert_equal(5, line('.'))
4152    autocmd! QuickFixCmdPost
4153  endif
4154
4155  " Test for vimgrep/lvimgrep
4156  call g:Xsetlist([], 'f')
4157  Xexpr 'Xtestfile1:2:Line2'
4158  autocmd QuickFixCmdPost * Xolder
4159  silent Xvimgrep Line5 Xtestfile2
4160  call assert_equal('Xtestfile2', @%)
4161  call assert_equal(5, line('.'))
4162  autocmd! QuickFixCmdPost
4163
4164  " Test for autocommands clearing the quickfix list before jumping to the
4165  " first error. This should not result in an error
4166  autocmd QuickFixCmdPost * call g:Xsetlist([], 'r')
4167  let v:errmsg = ''
4168  " Test for cfile/lfile
4169  Xfile Xerr
4170  call assert_true(v:errmsg !~# 'E42:')
4171  " Test for cbuffer/lbuffer
4172  edit Xerr
4173  Xbuffer
4174  call assert_true(v:errmsg !~# 'E42:')
4175  " Test for cexpr/lexpr
4176  Xexpr 'Xtestfile2:4:Line4'
4177  call assert_true(v:errmsg !~# 'E42:')
4178  " Test for grep/lgrep
4179  " The grepprg may not be set on non-Unix systems
4180  if has('unix')
4181    silent Xgrep Line5 Xtestfile2
4182    call assert_true(v:errmsg !~# 'E42:')
4183  endif
4184  " Test for vimgrep/lvimgrep
4185  call assert_fails('silent Xvimgrep Line5 Xtestfile2', 'E480:')
4186  autocmd! QuickFixCmdPost
4187
4188  call delete('Xerr')
4189  call delete('Xtestfile1')
4190  call delete('Xtestfile2')
4191endfunc
4192
4193func Test_autocmd_changelist()
4194  call Xautocmd_changelist('c')
4195  call Xautocmd_changelist('l')
4196endfunc
4197
4198" Tests for the ':filter /pat/ clist' command
4199func Test_filter_clist()
4200  cexpr ['Xfile1:10:10:Line 10', 'Xfile2:15:15:Line 15']
4201  call assert_equal([' 2 Xfile2:15 col 15: Line 15'],
4202			\ split(execute('filter /Line 15/ clist'), "\n"))
4203  call assert_equal([' 1 Xfile1:10 col 10: Line 10'],
4204			\ split(execute('filter /Xfile1/ clist'), "\n"))
4205  call assert_equal([], split(execute('filter /abc/ clist'), "\n"))
4206
4207  call setqflist([{'module' : 'abc', 'pattern' : 'pat1'},
4208			\ {'module' : 'pqr', 'pattern' : 'pat2'}], ' ')
4209  call assert_equal([' 2 pqr:pat2:  '],
4210			\ split(execute('filter /pqr/ clist'), "\n"))
4211  call assert_equal([' 1 abc:pat1:  '],
4212			\ split(execute('filter /pat1/ clist'), "\n"))
4213endfunc
4214
4215" Tests for the "CTRL-W <CR>" command.
4216func Xview_result_split_tests(cchar)
4217  call s:setup_commands(a:cchar)
4218
4219  " Test that "CTRL-W <CR>" in a qf/ll window fails with empty list.
4220  call g:Xsetlist([])
4221  Xopen
4222  let l:win_count = winnr('$')
4223  call assert_fails('execute "normal! \<C-W>\<CR>"', 'E42')
4224  call assert_equal(l:win_count, winnr('$'))
4225  Xclose
4226endfunc
4227
4228func Test_view_result_split()
4229  call Xview_result_split_tests('c')
4230  call Xview_result_split_tests('l')
4231endfunc
4232
4233" Test that :cc sets curswant
4234func Test_curswant()
4235  helpgrep quickfix
4236  normal! llll
4237  1cc
4238  call assert_equal(getcurpos()[4], virtcol('.'))
4239  cclose | helpclose
4240endfunc
4241
4242" Test for opening a file from the quickfix window using CTRL-W <Enter>
4243" doesn't leave an empty buffer around.
4244func Test_splitview()
4245  call s:create_test_file('Xtestfile1')
4246  call s:create_test_file('Xtestfile2')
4247  new | only
4248  let last_bufnr = bufnr('Test_sv_1', 1)
4249  let l = ['Xtestfile1:2:Line2', 'Xtestfile2:4:Line4']
4250  cgetexpr l
4251  copen
4252  let numbufs = len(getbufinfo())
4253  exe "normal \<C-W>\<CR>"
4254  copen
4255  exe "normal j\<C-W>\<CR>"
4256  " Make sure new empty buffers are not created
4257  call assert_equal(numbufs, len(getbufinfo()))
4258  " Creating a new buffer should use the next available buffer number
4259  call assert_equal(last_bufnr + 4, bufnr("Test_sv_2", 1))
4260  bwipe Test_sv_1
4261  bwipe Test_sv_2
4262  new | only
4263
4264  " When split opening files from location list window, make sure that two
4265  " windows doesn't refer to the same location list
4266  lgetexpr l
4267  let locid = getloclist(0, {'id' : 0}).id
4268  lopen
4269  exe "normal \<C-W>\<CR>"
4270  call assert_notequal(locid, getloclist(0, {'id' : 0}).id)
4271  call assert_equal(0, getloclist(0, {'winid' : 0}).winid)
4272  new | only
4273
4274  " When split opening files from a helpgrep location list window, a new help
4275  " window should be opened with a copy of the location list.
4276  lhelpgrep window
4277  let locid = getloclist(0, {'id' : 0}).id
4278  lwindow
4279  exe "normal j\<C-W>\<CR>"
4280  call assert_notequal(locid, getloclist(0, {'id' : 0}).id)
4281  call assert_equal(0, getloclist(0, {'winid' : 0}).winid)
4282  new | only
4283
4284  " Using :split or :vsplit from a quickfix window should behave like a :new
4285  " or a :vnew command
4286  copen
4287  split
4288  call assert_equal(3, winnr('$'))
4289  let l = getwininfo()
4290  call assert_equal([0, 0, 1], [l[0].quickfix, l[1].quickfix, l[2].quickfix])
4291  close
4292  copen
4293  vsplit
4294  let l = getwininfo()
4295  call assert_equal([0, 0, 1], [l[0].quickfix, l[1].quickfix, l[2].quickfix])
4296  new | only
4297
4298  call delete('Xtestfile1')
4299  call delete('Xtestfile2')
4300endfunc
4301
4302" Test for parsing entries using visual screen column
4303func Test_viscol()
4304  enew
4305  call writefile(["Col1\tCol2\tCol3"], 'Xfile1')
4306  edit Xfile1
4307
4308  " Use byte offset for column number
4309  set efm&
4310  cexpr "Xfile1:1:5:XX\nXfile1:1:9:YY\nXfile1:1:20:ZZ"
4311  call assert_equal([5, 8], [col('.'), virtcol('.')])
4312  cnext
4313  call assert_equal([9, 12], [col('.'), virtcol('.')])
4314  cnext
4315  call assert_equal([14, 20], [col('.'), virtcol('.')])
4316
4317  " Use screen column offset for column number
4318  set efm=%f:%l:%v:%m
4319  cexpr "Xfile1:1:8:XX\nXfile1:1:12:YY\nXfile1:1:20:ZZ"
4320  call assert_equal([5, 8], [col('.'), virtcol('.')])
4321  cnext
4322  call assert_equal([9, 12], [col('.'), virtcol('.')])
4323  cnext
4324  call assert_equal([14, 20], [col('.'), virtcol('.')])
4325  cexpr "Xfile1:1:6:XX\nXfile1:1:15:YY\nXfile1:1:24:ZZ"
4326  call assert_equal([5, 8], [col('.'), virtcol('.')])
4327  cnext
4328  call assert_equal([10, 16], [col('.'), virtcol('.')])
4329  cnext
4330  call assert_equal([14, 20], [col('.'), virtcol('.')])
4331
4332  enew
4333  call writefile(["Col1\täü\töß\tCol4"], 'Xfile1')
4334
4335  " Use byte offset for column number
4336  set efm&
4337  cexpr "Xfile1:1:8:XX\nXfile1:1:11:YY\nXfile1:1:16:ZZ"
4338  call assert_equal([8, 10], [col('.'), virtcol('.')])
4339  cnext
4340  call assert_equal([11, 17], [col('.'), virtcol('.')])
4341  cnext
4342  call assert_equal([16, 25], [col('.'), virtcol('.')])
4343
4344  " Use screen column offset for column number
4345  set efm=%f:%l:%v:%m
4346  cexpr "Xfile1:1:10:XX\nXfile1:1:17:YY\nXfile1:1:25:ZZ"
4347  call assert_equal([8, 10], [col('.'), virtcol('.')])
4348  cnext
4349  call assert_equal([11, 17], [col('.'), virtcol('.')])
4350  cnext
4351  call assert_equal([16, 25], [col('.'), virtcol('.')])
4352
4353  enew | only
4354  set efm&
4355  call delete('Xfile1')
4356endfunc
4357
4358" Test for the quickfix window buffer
4359func Xqfbuf_test(cchar)
4360  call s:setup_commands(a:cchar)
4361
4362  " Quickfix buffer should be reused across closing and opening a quickfix
4363  " window
4364  Xexpr "F1:10:Line10"
4365  Xopen
4366  let qfbnum = bufnr('')
4367  Xclose
4368  " Even after the quickfix window is closed, the buffer should be loaded
4369  call assert_true(bufloaded(qfbnum))
4370  call assert_true(qfbnum, g:Xgetlist({'qfbufnr' : 0}).qfbufnr)
4371  Xopen
4372  " Buffer should be reused when opening the window again
4373  call assert_equal(qfbnum, bufnr(''))
4374  Xclose
4375
4376  if a:cchar == 'l'
4377    %bwipe
4378    " For a location list, when both the file window and the location list
4379    " window for the list are closed, then the buffer should be freed.
4380    new | only
4381    lexpr "F1:10:Line10"
4382    let wid = win_getid()
4383    lopen
4384    let qfbnum = bufnr('')
4385    call assert_match(qfbnum . ' %a-  "\[Location List]"', execute('ls'))
4386    close
4387    " When the location list window is closed, the buffer name should not
4388    " change to 'Quickfix List'
4389    call assert_match(qfbnum . 'u h-  "\[Location List]"', execute('ls!'))
4390    call assert_true(bufloaded(qfbnum))
4391
4392    " After deleting a location list buffer using ":bdelete", opening the
4393    " location list window should mark the buffer as a location list buffer.
4394    exe "bdelete " . qfbnum
4395    lopen
4396    call assert_equal("quickfix", &buftype)
4397    call assert_equal(1, getwininfo(win_getid(winnr()))[0].loclist)
4398    call assert_equal(wid, getloclist(0, {'filewinid' : 0}).filewinid)
4399    call assert_false(&swapfile)
4400    lclose
4401
4402    " When the location list is cleared for the window, the buffer should be
4403    " removed
4404    call setloclist(0, [], 'f')
4405    call assert_false(bufexists(qfbnum))
4406    call assert_equal(0, getloclist(0, {'qfbufnr' : 0}).qfbufnr)
4407
4408    " When the location list is freed with the location list window open, the
4409    " location list buffer should not be lost. It should be reused when the
4410    " location list is again populated.
4411    lexpr "F1:10:Line10"
4412    lopen
4413    let wid = win_getid()
4414    let qfbnum = bufnr('')
4415    wincmd p
4416    call setloclist(0, [], 'f')
4417    lexpr "F1:10:Line10"
4418    lopen
4419    call assert_equal(wid, win_getid())
4420    call assert_equal(qfbnum, bufnr(''))
4421    lclose
4422
4423    " When the window with the location list is closed, the buffer should be
4424    " removed
4425    new | only
4426    call assert_false(bufexists(qfbnum))
4427  endif
4428endfunc
4429
4430func Test_qfbuf()
4431  call Xqfbuf_test('c')
4432  call Xqfbuf_test('l')
4433endfunc
4434
4435" If there is an autocmd to use only one window, then opening the location
4436" list window used to crash Vim.
4437func Test_winonly_autocmd()
4438  call s:create_test_file('Xtest1')
4439  " Autocmd to show only one Vim window at a time
4440  autocmd WinEnter * only
4441  new
4442  " Load the location list
4443  lexpr "Xtest1:5:Line5\nXtest1:10:Line10\nXtest1:15:Line15"
4444  let loclistid = getloclist(0, {'id' : 0}).id
4445  " Open the location list window. Only this window will be shown and the file
4446  " window is closed.
4447  lopen
4448  call assert_equal(loclistid, getloclist(0, {'id' : 0}).id)
4449  " Jump to an entry in the location list and make sure that the cursor is
4450  " positioned correctly.
4451  ll 3
4452  call assert_equal(loclistid, getloclist(0, {'id' : 0}).id)
4453  call assert_equal('Xtest1', @%)
4454  call assert_equal(15, line('.'))
4455  " Cleanup
4456  autocmd! WinEnter
4457  new | only
4458  call delete('Xtest1')
4459endfunc
4460
4461" Test to make sure that an empty quickfix buffer is not reused for loading
4462" a normal buffer.
4463func Test_empty_qfbuf()
4464  enew | only
4465  call writefile(["Test"], 'Xfile1')
4466  call setqflist([], 'f')
4467  copen | only
4468  let qfbuf = bufnr('')
4469  edit Xfile1
4470  call assert_notequal(qfbuf, bufnr(''))
4471  enew
4472  call delete('Xfile1')
4473endfunc
4474
4475" Test for the :cbelow, :cabove, :lbelow and :labove commands.
4476" And for the :cafter, :cbefore, :lafter and :lbefore commands.
4477func Xtest_below(cchar)
4478  call s:setup_commands(a:cchar)
4479
4480  " No quickfix/location list
4481  call assert_fails('Xbelow', 'E42:')
4482  call assert_fails('Xabove', 'E42:')
4483  call assert_fails('Xbefore', 'E42:')
4484  call assert_fails('Xafter', 'E42:')
4485
4486  " Empty quickfix/location list
4487  call g:Xsetlist([])
4488  call assert_fails('Xbelow', 'E42:')
4489  call assert_fails('Xabove', 'E42:')
4490  call assert_fails('Xbefore', 'E42:')
4491  call assert_fails('Xafter', 'E42:')
4492
4493  call s:create_test_file('X1')
4494  call s:create_test_file('X2')
4495  call s:create_test_file('X3')
4496  call s:create_test_file('X4')
4497
4498  " Invalid entries
4499  edit X1
4500  call g:Xsetlist(["E1", "E2"])
4501  call assert_fails('Xbelow', 'E42:')
4502  call assert_fails('Xabove', 'E42:')
4503  call assert_fails('3Xbelow', 'E42:')
4504  call assert_fails('4Xabove', 'E42:')
4505  call assert_fails('Xbefore', 'E42:')
4506  call assert_fails('Xafter', 'E42:')
4507  call assert_fails('3Xbefore', 'E42:')
4508  call assert_fails('4Xafter', 'E42:')
4509
4510  " Test the commands with various arguments
4511  Xexpr ["X1:5:3:L5", "X2:5:2:L5", "X2:10:3:L10", "X2:15:4:L15", "X3:3:5:L3"]
4512  edit +7 X2
4513  Xabove
4514  call assert_equal(['X2', 5], [@%, line('.')])
4515  call assert_fails('Xabove', 'E553:')
4516  normal 7G
4517  Xbefore
4518  call assert_equal(['X2', 5, 2], [@%, line('.'), col('.')])
4519  call assert_fails('Xbefore', 'E553:')
4520
4521  normal 2j
4522  Xbelow
4523  call assert_equal(['X2', 10], [@%, line('.')])
4524  normal 7G
4525  Xafter
4526  call assert_equal(['X2', 10, 3], [@%, line('.'), col('.')])
4527
4528  " Last error in this file
4529  Xbelow 99
4530  call assert_equal(['X2', 15], [@%, line('.')])
4531  call assert_fails('Xbelow', 'E553:')
4532  normal gg
4533  Xafter 99
4534  call assert_equal(['X2', 15, 4], [@%, line('.'), col('.')])
4535  call assert_fails('Xafter', 'E553:')
4536
4537  " First error in this file
4538  Xabove 99
4539  call assert_equal(['X2', 5], [@%, line('.')])
4540  call assert_fails('Xabove', 'E553:')
4541  normal G
4542  Xbefore 99
4543  call assert_equal(['X2', 5, 2], [@%, line('.'), col('.')])
4544  call assert_fails('Xbefore', 'E553:')
4545
4546  normal gg
4547  Xbelow 2
4548  call assert_equal(['X2', 10], [@%, line('.')])
4549  normal gg
4550  Xafter 2
4551  call assert_equal(['X2', 10, 3], [@%, line('.'), col('.')])
4552
4553  normal G
4554  Xabove 2
4555  call assert_equal(['X2', 10], [@%, line('.')])
4556  normal G
4557  Xbefore 2
4558  call assert_equal(['X2', 10, 3], [@%, line('.'), col('.')])
4559
4560  edit X4
4561  call assert_fails('Xabove', 'E42:')
4562  call assert_fails('Xbelow', 'E42:')
4563  call assert_fails('Xbefore', 'E42:')
4564  call assert_fails('Xafter', 'E42:')
4565  if a:cchar == 'l'
4566    " If a buffer has location list entries from some other window but not
4567    " from the current window, then the commands should fail.
4568    edit X1 | split | call setloclist(0, [], 'f')
4569    call assert_fails('Xabove', 'E776:')
4570    call assert_fails('Xbelow', 'E776:')
4571    call assert_fails('Xbefore', 'E776:')
4572    call assert_fails('Xafter', 'E776:')
4573    close
4574  endif
4575
4576  " Test for lines with multiple quickfix entries
4577  Xexpr ["X1:5:L5", "X2:5:1:L5_1", "X2:5:2:L5_2", "X2:5:3:L5_3",
4578	      \ "X2:10:1:L10_1", "X2:10:2:L10_2", "X2:10:3:L10_3",
4579	      \ "X2:15:1:L15_1", "X2:15:2:L15_2", "X2:15:3:L15_3", "X3:3:L3"]
4580  edit +1 X2
4581  Xbelow 2
4582  call assert_equal(['X2', 10, 1], [@%, line('.'), col('.')])
4583  normal 1G
4584  Xafter 2
4585  call assert_equal(['X2', 5, 2], [@%, line('.'), col('.')])
4586
4587  normal gg
4588  Xbelow 99
4589  call assert_equal(['X2', 15, 1], [@%, line('.'), col('.')])
4590  normal gg
4591  Xafter 99
4592  call assert_equal(['X2', 15, 3], [@%, line('.'), col('.')])
4593
4594  normal G
4595  Xabove 2
4596  call assert_equal(['X2', 10, 1], [@%, line('.'), col('.')])
4597  normal G
4598  Xbefore 2
4599  call assert_equal(['X2', 15, 2], [@%, line('.'), col('.')])
4600
4601  normal G
4602  Xabove 99
4603  call assert_equal(['X2', 5, 1], [@%, line('.'), col('.')])
4604  normal G
4605  Xbefore 99
4606  call assert_equal(['X2', 5, 1], [@%, line('.'), col('.')])
4607
4608  normal 10G
4609  Xabove
4610  call assert_equal(['X2', 5, 1], [@%, line('.'), col('.')])
4611  normal 10G$
4612  2Xbefore
4613  call assert_equal(['X2', 10, 2], [@%, line('.'), col('.')])
4614
4615  normal 10G
4616  Xbelow
4617  call assert_equal(['X2', 15, 1], [@%, line('.'), col('.')])
4618  normal 9G
4619  5Xafter
4620  call assert_equal(['X2', 15, 2], [@%, line('.'), col('.')])
4621
4622  " Invalid range
4623  if a:cchar == 'c'
4624    call assert_fails('-2cbelow', 'E16:')
4625    call assert_fails('-2cafter', 'E16:')
4626  else
4627    call assert_fails('-2lbelow', 'E16:')
4628    call assert_fails('-2lafter', 'E16:')
4629  endif
4630
4631  call delete('X1')
4632  call delete('X2')
4633  call delete('X3')
4634  call delete('X4')
4635endfunc
4636
4637func Test_cbelow()
4638  call Xtest_below('c')
4639  call Xtest_below('l')
4640endfunc
4641
4642func Test_quickfix_count()
4643  let commands = [
4644	\ 'cNext',
4645	\ 'cNfile',
4646	\ 'cabove',
4647	\ 'cbelow',
4648	\ 'cfirst',
4649	\ 'clast',
4650	\ 'cnewer',
4651	\ 'cnext',
4652	\ 'cnfile',
4653	\ 'colder',
4654	\ 'cprevious',
4655	\ 'crewind',
4656	\
4657	\ 'lNext',
4658	\ 'lNfile',
4659	\ 'labove',
4660	\ 'lbelow',
4661	\ 'lfirst',
4662	\ 'llast',
4663	\ 'lnewer',
4664	\ 'lnext',
4665	\ 'lnfile',
4666	\ 'lolder',
4667	\ 'lprevious',
4668	\ 'lrewind',
4669	\ ]
4670  for cmd in commands
4671    call assert_fails('-1' .. cmd, 'E16:')
4672    call assert_fails('.' .. cmd, 'E16:')
4673    call assert_fails('%' .. cmd, 'E16:')
4674    call assert_fails('$' .. cmd, 'E16:')
4675  endfor
4676endfunc
4677
4678" Test for aborting quickfix commands using QuickFixCmdPre
4679func Xtest_qfcmd_abort(cchar)
4680  call s:setup_commands(a:cchar)
4681
4682  call g:Xsetlist([], 'f')
4683
4684  " cexpr/lexpr
4685  let e = ''
4686  try
4687    Xexpr ["F1:10:Line10", "F2:20:Line20"]
4688  catch /.*/
4689    let e = v:exception
4690  endtry
4691  call assert_equal('AbortCmd', e)
4692  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4693
4694  " cfile/lfile
4695  call writefile(["F1:10:Line10", "F2:20:Line20"], 'Xfile1')
4696  let e = ''
4697  try
4698    Xfile Xfile1
4699  catch /.*/
4700    let e = v:exception
4701  endtry
4702  call assert_equal('AbortCmd', e)
4703  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4704  call delete('Xfile1')
4705
4706  " cgetbuffer/lgetbuffer
4707  enew!
4708  call append(0, ["F1:10:Line10", "F2:20:Line20"])
4709  let e = ''
4710  try
4711    Xgetbuffer
4712  catch /.*/
4713    let e = v:exception
4714  endtry
4715  call assert_equal('AbortCmd', e)
4716  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4717  enew!
4718
4719  " vimgrep/lvimgrep
4720  let e = ''
4721  try
4722    Xvimgrep /func/ test_quickfix.vim
4723  catch /.*/
4724    let e = v:exception
4725  endtry
4726  call assert_equal('AbortCmd', e)
4727  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4728
4729  " helpgrep/lhelpgrep
4730  let e = ''
4731  try
4732    Xhelpgrep quickfix
4733  catch /.*/
4734    let e = v:exception
4735  endtry
4736  call assert_equal('AbortCmd', e)
4737  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4738
4739  " grep/lgrep
4740  if has('unix')
4741    let e = ''
4742    try
4743      silent Xgrep func test_quickfix.vim
4744    catch /.*/
4745      let e = v:exception
4746    endtry
4747    call assert_equal('AbortCmd', e)
4748    call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4749  endif
4750endfunc
4751
4752func Test_qfcmd_abort()
4753  augroup QF_Test
4754    au!
4755    autocmd  QuickFixCmdPre * throw "AbortCmd"
4756  augroup END
4757
4758  call Xtest_qfcmd_abort('c')
4759  call Xtest_qfcmd_abort('l')
4760
4761  augroup QF_Test
4762    au!
4763  augroup END
4764endfunc
4765
4766" Test for using a file in one of the parent directories.
4767func Test_search_in_dirstack()
4768  call mkdir('Xtestdir/a/b/c', 'p')
4769  let save_cwd = getcwd()
4770  call writefile(["X1_L1", "X1_L2"], 'Xtestdir/Xfile1')
4771  call writefile(["X2_L1", "X2_L2"], 'Xtestdir/a/Xfile2')
4772  call writefile(["X3_L1", "X3_L2"], 'Xtestdir/a/b/Xfile3')
4773  call writefile(["X4_L1", "X4_L2"], 'Xtestdir/a/b/c/Xfile4')
4774
4775  let lines = "Entering dir Xtestdir\n" .
4776	      \ "Entering dir a\n" .
4777	      \ "Entering dir b\n" .
4778	      \ "Xfile2:2:X2_L2\n" .
4779	      \ "Leaving dir a\n" .
4780	      \ "Xfile1:2:X1_L2\n" .
4781	      \ "Xfile3:1:X3_L1\n" .
4782	      \ "Entering dir c\n" .
4783	      \ "Xfile4:2:X4_L2\n" .
4784	      \ "Leaving dir c\n"
4785  set efm=%DEntering\ dir\ %f,%XLeaving\ dir\ %f,%f:%l:%m
4786  cexpr lines .. "Leaving dir Xtestdir|\n" | let next = 1
4787  call assert_equal(11, getqflist({'size' : 0}).size)
4788  call assert_equal(4, getqflist({'idx' : 0}).idx)
4789  call assert_equal('X2_L2', getline('.'))
4790  call assert_equal(1, next)
4791  cnext
4792  call assert_equal(6, getqflist({'idx' : 0}).idx)
4793  call assert_equal('X1_L2', getline('.'))
4794  cnext
4795  call assert_equal(7, getqflist({'idx' : 0}).idx)
4796  call assert_equal(1, line('$'))
4797  call assert_equal('', getline(1))
4798  cnext
4799  call assert_equal(9, getqflist({'idx' : 0}).idx)
4800  call assert_equal(1, line('$'))
4801  call assert_equal('', getline(1))
4802
4803  set efm&
4804  exe 'cd ' . save_cwd
4805  call delete('Xtestdir', 'rf')
4806endfunc
4807
4808" Test for :cquit
4809func Test_cquit()
4810  " Exit Vim with a non-zero value
4811  if RunVim([], ["cquit 7"], '')
4812    call assert_equal(7, v:shell_error)
4813  endif
4814
4815  if RunVim([], ["50cquit"], '')
4816    call assert_equal(50, v:shell_error)
4817  endif
4818
4819  " Exit Vim with default value
4820  if RunVim([], ["cquit"], '')
4821    call assert_equal(1, v:shell_error)
4822  endif
4823
4824  " Exit Vim with zero value
4825  if RunVim([], ["cquit 0"], '')
4826    call assert_equal(0, v:shell_error)
4827  endif
4828
4829  " Exit Vim with negative value
4830  call assert_fails('-3cquit', 'E16:')
4831endfunc
4832
4833" Test for getting a specific item from a quickfix list
4834func Xtest_getqflist_by_idx(cchar)
4835  call s:setup_commands(a:cchar)
4836  " Empty list
4837  call assert_equal([], g:Xgetlist({'idx' : 1, 'items' : 0}).items)
4838  Xexpr ['F1:10:L10', 'F1:20:L20']
4839  let l = g:Xgetlist({'idx' : 2, 'items' : 0}).items
4840  call assert_equal(bufnr('F1'), l[0].bufnr)
4841  call assert_equal(20, l[0].lnum)
4842  call assert_equal('L20', l[0].text)
4843  call assert_equal([], g:Xgetlist({'idx' : -1, 'items' : 0}).items)
4844  call assert_equal([], g:Xgetlist({'idx' : 3, 'items' : 0}).items)
4845  %bwipe!
4846endfunc
4847
4848func Test_getqflist_by_idx()
4849  call Xtest_getqflist_by_idx('c')
4850  call Xtest_getqflist_by_idx('l')
4851endfunc
4852
4853" Test for the 'quickfixtextfunc' setting
4854func Tqfexpr(info)
4855  if a:info.quickfix
4856    let qfl = getqflist({'id' : a:info.id, 'items' : 1}).items
4857  else
4858    let qfl = getloclist(a:info.winid, {'id' : a:info.id, 'items' : 1}).items
4859  endif
4860
4861  let l = []
4862  for idx in range(a:info.start_idx - 1, a:info.end_idx - 1)
4863    let e = qfl[idx]
4864    let s = ''
4865    if e.bufnr != 0
4866      let bname = bufname(e.bufnr)
4867      let s ..= fnamemodify(bname, ':.')
4868    endif
4869    let s ..= '-'
4870    let s ..= 'L' .. string(e.lnum) .. 'C' .. string(e.col) .. '-'
4871    let s ..= e.text
4872    call add(l, s)
4873  endfor
4874
4875  return l
4876endfunc
4877
4878func Xtest_qftextfunc(cchar)
4879  call s:setup_commands(a:cchar)
4880
4881  set efm=%f:%l:%c:%m
4882  set quickfixtextfunc=Tqfexpr
4883  call assert_equal('Tqfexpr', &quickfixtextfunc)
4884  call assert_equal('',
4885        \ g:Xgetlist({'quickfixtextfunc' : 1}).quickfixtextfunc)
4886  Xexpr ['F1:10:2:green', 'F1:20:4:blue']
4887  Xwindow
4888  call assert_equal('F1-L10C2-green', getline(1))
4889  call assert_equal('F1-L20C4-blue', getline(2))
4890  Xclose
4891  set quickfixtextfunc&vim
4892  Xwindow
4893  call assert_equal('F1|10 col 2| green', getline(1))
4894  call assert_equal('F1|20 col 4| blue', getline(2))
4895  Xclose
4896  set efm&
4897  set quickfixtextfunc&
4898
4899  " Test for per list 'quickfixtextfunc' setting
4900  func PerQfText(info)
4901    if a:info.quickfix
4902      let qfl = getqflist({'id' : a:info.id, 'items' : 1}).items
4903    else
4904      let qfl = getloclist(a:info.winid, {'id' : a:info.id, 'items' : 1}).items
4905    endif
4906    if empty(qfl)
4907      return []
4908    endif
4909    let l = []
4910    for idx in range(a:info.start_idx - 1, a:info.end_idx - 1)
4911      call add(l, 'Line ' .. qfl[idx].lnum .. ', Col ' .. qfl[idx].col)
4912    endfor
4913    return l
4914  endfunc
4915  set quickfixtextfunc=Tqfexpr
4916  call g:Xsetlist([], ' ', {'quickfixtextfunc' : "PerQfText"})
4917  Xaddexpr ['F1:10:2:green', 'F1:20:4:blue']
4918  Xwindow
4919  call assert_equal('Line 10, Col 2', getline(1))
4920  call assert_equal('Line 20, Col 4', getline(2))
4921  Xclose
4922  call assert_equal(function('PerQfText'),
4923        \ g:Xgetlist({'quickfixtextfunc' : 1}).quickfixtextfunc)
4924  " Add entries to the list when the quickfix buffer is hidden
4925  Xaddexpr ['F1:30:6:red']
4926  Xwindow
4927  call assert_equal('Line 30, Col 6', getline(3))
4928  Xclose
4929  call g:Xsetlist([], 'r', {'quickfixtextfunc' : ''})
4930  call assert_equal('', g:Xgetlist({'quickfixtextfunc' : 1}).quickfixtextfunc)
4931  set quickfixtextfunc&
4932  delfunc PerQfText
4933
4934  " Non-existing function
4935  set quickfixtextfunc=Tabc
4936  call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue']", 'E117:')
4937  call assert_fails("Xwindow", 'E117:')
4938  Xclose
4939  set quickfixtextfunc&
4940
4941  " set option to a non-function
4942  set quickfixtextfunc=[10,\ 20]
4943  call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue']", 'E117:')
4944  call assert_fails("Xwindow", 'E117:')
4945  Xclose
4946  set quickfixtextfunc&
4947
4948  " set option to a function with different set of arguments
4949  func Xqftext(a, b, c)
4950    return a:a .. a:b .. a:c
4951  endfunc
4952  set quickfixtextfunc=Xqftext
4953  call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue']", 'E119:')
4954  call assert_fails("Xwindow", 'E119:')
4955  Xclose
4956
4957  " set option to a function that returns a list with non-strings
4958  func Xqftext2(d)
4959    return ['one', [], 'two']
4960  endfunc
4961  set quickfixtextfunc=Xqftext2
4962  call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue', 'F1:30:6:red']",
4963                                                                  \ 'E730:')
4964  call assert_fails('Xwindow', 'E730:')
4965  call assert_equal(['one', 'F1|20 col 4| blue', 'F1|30 col 6| red'],
4966        \ getline(1, '$'))
4967  Xclose
4968
4969  set quickfixtextfunc&
4970  delfunc Xqftext
4971  delfunc Xqftext2
4972
4973  " set the global option to a lambda function
4974  set quickfixtextfunc={d\ ->\ map(g:Xgetlist({'id'\ :\ d.id,\ 'items'\ :\ 1}).items[d.start_idx-1:d.end_idx-1],\ 'v:val.text')}
4975  Xexpr ['F1:10:2:green', 'F1:20:4:blue']
4976  Xwindow
4977  call assert_equal(['green', 'blue'], getline(1, '$'))
4978  Xclose
4979  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)
4980  set quickfixtextfunc&
4981
4982  " use a lambda function that returns an empty list
4983  set quickfixtextfunc={d\ ->\ []}
4984  Xexpr ['F1:10:2:green', 'F1:20:4:blue']
4985  Xwindow
4986  call assert_equal(['F1|10 col 2| green', 'F1|20 col 4| blue'],
4987        \ getline(1, '$'))
4988  Xclose
4989  set quickfixtextfunc&
4990
4991  " use a lambda function that returns a list with empty strings
4992  set quickfixtextfunc={d\ ->\ ['',\ '']}
4993  Xexpr ['F1:10:2:green', 'F1:20:4:blue']
4994  Xwindow
4995  call assert_equal(['F1|10 col 2| green', 'F1|20 col 4| blue'],
4996        \ getline(1, '$'))
4997  Xclose
4998  set quickfixtextfunc&
4999
5000  " set the per-quickfix list text function to a lambda function
5001  call g:Xsetlist([], ' ',
5002        \ {'quickfixtextfunc' :
5003        \   {d -> map(g:Xgetlist({'id' : d.id, 'items' : 1}).items[d.start_idx-1:d.end_idx-1],
5004        \ "'Line ' .. v:val.lnum .. ', Col ' .. v:val.col")}})
5005  Xaddexpr ['F1:10:2:green', 'F1:20:4:blue']
5006  Xwindow
5007  call assert_equal('Line 10, Col 2', getline(1))
5008  call assert_equal('Line 20, Col 4', getline(2))
5009  Xclose
5010  call assert_match("function('<lambda>\\d\\+')", string(g:Xgetlist({'quickfixtextfunc' : 1}).quickfixtextfunc))
5011  call g:Xsetlist([], 'f')
5012endfunc
5013
5014func Test_qftextfunc()
5015  call Xtest_qftextfunc('c')
5016  call Xtest_qftextfunc('l')
5017endfunc
5018
5019" Running :lhelpgrep command more than once in a help window, doesn't jump to
5020" the help topic
5021func Test_lhelpgrep_from_help_window()
5022  call mkdir('Xtestdir/doc', 'p')
5023  call writefile(['window'], 'Xtestdir/doc/a.txt')
5024  call writefile(['buffer'], 'Xtestdir/doc/b.txt')
5025  let save_rtp = &rtp
5026  let &rtp = 'Xtestdir'
5027  lhelpgrep window
5028  lhelpgrep buffer
5029  call assert_equal('b.txt', fnamemodify(@%, ":p:t"))
5030  lhelpgrep window
5031  call assert_equal('a.txt', fnamemodify(@%, ":p:t"))
5032  let &rtp = save_rtp
5033  call delete('Xtestdir', 'rf')
5034  new | only!
5035endfunc
5036
5037" Test for the crash fixed by 7.3.715
5038func Test_setloclist_crash()
5039  %bw!
5040  let g:BufNum = bufnr()
5041  augroup QF_Test
5042    au!
5043    au BufUnload * call setloclist(0, [{'bufnr':g:BufNum, 'lnum':1, 'col':1, 'text': 'tango down'}])
5044  augroup END
5045
5046  try
5047    lvimgrep /.*/ *.mak
5048  catch /E926:/
5049  endtry
5050  call assert_equal('tango down', getloclist(0, {'items' : 0}).items[0].text)
5051  call assert_equal(1, getloclist(0, {'size' : 0}).size)
5052
5053  augroup QF_Test
5054    au!
5055  augroup END
5056  unlet g:BufNum
5057  %bw!
5058endfunc
5059
5060" vim: shiftwidth=2 sts=2 expandtab
5061