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