1" Test for the quickfix feature.
2
3source check.vim
4CheckFeature quickfix
5
6source screendump.vim
7
8set encoding=utf-8
9
10func s:setup_commands(cchar)
11  if a:cchar == 'c'
12    command! -nargs=* -bang Xlist <mods>clist<bang> <args>
13    command! -nargs=* Xgetexpr <mods>cgetexpr <args>
14    command! -nargs=* Xaddexpr <mods>caddexpr <args>
15    command! -nargs=* -count Xolder <mods><count>colder <args>
16    command! -nargs=* Xnewer <mods>cnewer <args>
17    command! -nargs=* Xopen <mods> copen <args>
18    command! -nargs=* Xwindow <mods>cwindow <args>
19    command! -nargs=* Xbottom <mods>cbottom <args>
20    command! -nargs=* Xclose <mods>cclose <args>
21    command! -nargs=* -bang Xfile <mods>cfile<bang> <args>
22    command! -nargs=* Xgetfile <mods>cgetfile <args>
23    command! -nargs=* Xaddfile <mods>caddfile <args>
24    command! -nargs=* -bang Xbuffer <mods>cbuffer<bang> <args>
25    command! -nargs=* Xgetbuffer <mods>cgetbuffer <args>
26    command! -nargs=* Xaddbuffer <mods>caddbuffer <args>
27    command! -nargs=* Xrewind <mods>crewind <args>
28    command! -count -nargs=* -bang Xnext <mods><count>cnext<bang> <args>
29    command! -count -nargs=* -bang Xprev <mods><count>cprev<bang> <args>
30    command! -nargs=* -bang Xfirst <mods>cfirst<bang> <args>
31    command! -nargs=* -bang Xlast <mods>clast<bang> <args>
32    command! -count -nargs=* -bang Xnfile <mods><count>cnfile<bang> <args>
33    command! -nargs=* -bang Xpfile <mods>cpfile<bang> <args>
34    command! -nargs=* Xexpr <mods>cexpr <args>
35    command! -count -nargs=* Xvimgrep <mods> <count>vimgrep <args>
36    command! -nargs=* Xvimgrepadd <mods> vimgrepadd <args>
37    command! -nargs=* Xgrep <mods> grep <args>
38    command! -nargs=* Xgrepadd <mods> grepadd <args>
39    command! -nargs=* Xhelpgrep helpgrep <args>
40    command! -nargs=0 -count Xcc <count>cc
41    command! -count=1 -nargs=0 Xbelow <mods><count>cbelow
42    command! -count=1 -nargs=0 Xabove <mods><count>cabove
43    command! -count=1 -nargs=0 Xbefore <mods><count>cbefore
44    command! -count=1 -nargs=0 Xafter <mods><count>cafter
45    let g:Xgetlist = function('getqflist')
46    let g:Xsetlist = function('setqflist')
47    call setqflist([], 'f')
48  else
49    command! -nargs=* -bang Xlist <mods>llist<bang> <args>
50    command! -nargs=* Xgetexpr <mods>lgetexpr <args>
51    command! -nargs=* Xaddexpr <mods>laddexpr <args>
52    command! -nargs=* -count Xolder <mods><count>lolder <args>
53    command! -nargs=* Xnewer <mods>lnewer <args>
54    command! -nargs=* Xopen <mods> lopen <args>
55    command! -nargs=* Xwindow <mods>lwindow <args>
56    command! -nargs=* Xbottom <mods>lbottom <args>
57    command! -nargs=* Xclose <mods>lclose <args>
58    command! -nargs=* -bang Xfile <mods>lfile<bang> <args>
59    command! -nargs=* Xgetfile <mods>lgetfile <args>
60    command! -nargs=* Xaddfile <mods>laddfile <args>
61    command! -nargs=* -bang Xbuffer <mods>lbuffer<bang> <args>
62    command! -nargs=* Xgetbuffer <mods>lgetbuffer <args>
63    command! -nargs=* Xaddbuffer <mods>laddbuffer <args>
64    command! -nargs=* Xrewind <mods>lrewind <args>
65    command! -count -nargs=* -bang Xnext <mods><count>lnext<bang> <args>
66    command! -count -nargs=* -bang Xprev <mods><count>lprev<bang> <args>
67    command! -nargs=* -bang Xfirst <mods>lfirst<bang> <args>
68    command! -nargs=* -bang Xlast <mods>llast<bang> <args>
69    command! -count -nargs=* -bang Xnfile <mods><count>lnfile<bang> <args>
70    command! -nargs=* -bang Xpfile <mods>lpfile<bang> <args>
71    command! -nargs=* Xexpr <mods>lexpr <args>
72    command! -count -nargs=* Xvimgrep <mods> <count>lvimgrep <args>
73    command! -nargs=* Xvimgrepadd <mods> lvimgrepadd <args>
74    command! -nargs=* Xgrep <mods> lgrep <args>
75    command! -nargs=* Xgrepadd <mods> lgrepadd <args>
76    command! -nargs=* Xhelpgrep lhelpgrep <args>
77    command! -nargs=0 -count Xcc <count>ll
78    command! -count=1 -nargs=0 Xbelow <mods><count>lbelow
79    command! -count=1 -nargs=0 Xabove <mods><count>labove
80    command! -count=1 -nargs=0 Xbefore <mods><count>lbefore
81    command! -count=1 -nargs=0 Xafter <mods><count>lafter
82    let g:Xgetlist = function('getloclist', [0])
83    let g:Xsetlist = function('setloclist', [0])
84    call setloclist(0, [], 'f')
85  endif
86endfunc
87
88" Tests for the :clist and :llist commands
89func XlistTests(cchar)
90  call s:setup_commands(a:cchar)
91
92  if a:cchar == 'l'
93      call assert_fails('llist', 'E776:')
94  endif
95  " With an empty list, command should return error
96  Xgetexpr []
97  silent! Xlist
98  call assert_true(v:errmsg ==# 'E42: No Errors')
99
100  " Populate the list and then try
101  Xgetexpr ['non-error 1', 'Xtestfile1:1:3:Line1',
102		  \ 'non-error 2', 'Xtestfile2:2:2:Line2',
103		  \ 'non-error| 3', 'Xtestfile3:3:1:Line3']
104
105  " List only valid entries
106  let l = split(execute('Xlist', ''), "\n")
107  call assert_equal([' 2 Xtestfile1:1 col 3: Line1',
108		   \ ' 4 Xtestfile2:2 col 2: Line2',
109		   \ ' 6 Xtestfile3:3 col 1: Line3'], l)
110
111  " List all the entries
112  let l = split(execute('Xlist!', ''), "\n")
113  call assert_equal([' 1: non-error 1', ' 2 Xtestfile1:1 col 3: Line1',
114		   \ ' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2',
115		   \ ' 5: non-error| 3', ' 6 Xtestfile3:3 col 1: Line3'], l)
116
117  " List a range of errors
118  let l = split(execute('Xlist 3,6', ''), "\n")
119  call assert_equal([' 4 Xtestfile2:2 col 2: Line2',
120		   \ ' 6 Xtestfile3:3 col 1: Line3'], l)
121
122  let l = split(execute('Xlist! 3,4', ''), "\n")
123  call assert_equal([' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2'], l)
124
125  let l = split(execute('Xlist -6,-4', ''), "\n")
126  call assert_equal([' 2 Xtestfile1:1 col 3: Line1'], l)
127
128  let l = split(execute('Xlist! -5,-3', ''), "\n")
129  call assert_equal([' 2 Xtestfile1:1 col 3: Line1',
130		   \ ' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2'], l)
131
132  " Test for '+'
133  let l = split(execute('Xlist! +2', ''), "\n")
134  call assert_equal([' 2 Xtestfile1:1 col 3: Line1',
135		   \ ' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2'], l)
136
137  " Different types of errors
138  call g:Xsetlist([{'lnum':10,'col':5,'type':'W', 'text':'Warning','nr':11},
139	      \ {'lnum':20,'col':10,'type':'e','text':'Error','nr':22},
140	      \ {'lnum':30,'col':15,'type':'i','text':'Info','nr':33},
141	      \ {'lnum':40,'col':20,'type':'x', 'text':'Other','nr':44},
142	      \ {'lnum':50,'col':25,'type':"\<C-A>",'text':'one','nr':55}])
143  let l = split(execute('Xlist', ""), "\n")
144  call assert_equal([' 1:10 col 5 warning  11: Warning',
145	      \ ' 2:20 col 10 error  22: Error',
146	      \ ' 3:30 col 15 info  33: Info',
147	      \ ' 4:40 col 20 x  44: Other',
148	      \ ' 5:50 col 25  55: one'], l)
149
150  " Test for module names, one needs to explicitly set `'valid':v:true` so
151  call g:Xsetlist([
152	\ {'lnum':10,'col':5,'type':'W','module':'Data.Text','text':'ModuleWarning','nr':11,'valid':v:true},
153	\ {'lnum':20,'col':10,'type':'W','module':'Data.Text','filename':'Data/Text.hs','text':'ModuleWarning','nr':22,'valid':v:true},
154	\ {'lnum':30,'col':15,'type':'W','filename':'Data/Text.hs','text':'FileWarning','nr':33,'valid':v:true}])
155  let l = split(execute('Xlist', ""), "\n")
156  call assert_equal([' 1 Data.Text:10 col 5 warning  11: ModuleWarning',
157	\ ' 2 Data.Text:20 col 10 warning  22: ModuleWarning',
158	\ ' 3 Data/Text.hs:30 col 15 warning  33: FileWarning'], l)
159
160  " For help entries in the quickfix list, only the filename without directory
161  " should be displayed
162  Xhelpgrep setqflist()
163  let l = split(execute('Xlist 1', ''), "\n")
164  call assert_match('^ 1 [^\\/]\{-}:', l[0])
165
166  " Error cases
167  call assert_fails('Xlist abc', 'E488:')
168endfunc
169
170func Test_clist()
171  call XlistTests('c')
172  call XlistTests('l')
173endfunc
174
175" Tests for the :colder, :cnewer, :lolder and :lnewer commands
176" Note that this test assumes that a quickfix/location list is
177" already set by the caller.
178func XageTests(cchar)
179  call s:setup_commands(a:cchar)
180
181  if a:cchar == 'l'
182    " No location list for the current window
183    call assert_fails('lolder', 'E776:')
184    call assert_fails('lnewer', 'E776:')
185  endif
186
187  let list = [{'bufnr': bufnr('%'), 'lnum': 1}]
188  call g:Xsetlist(list)
189
190  " Jumping to a non existent list should return error
191  silent! Xolder 99
192  call assert_true(v:errmsg ==# 'E380: At bottom of quickfix stack')
193
194  silent! Xnewer 99
195  call assert_true(v:errmsg ==# 'E381: At top of quickfix stack')
196
197  " Add three quickfix/location lists
198  Xgetexpr ['Xtestfile1:1:3:Line1']
199  Xgetexpr ['Xtestfile2:2:2:Line2']
200  Xgetexpr ['Xtestfile3:3:1:Line3']
201
202  " Go back two lists
203  Xolder
204  let l = g:Xgetlist()
205  call assert_equal('Line2', l[0].text)
206
207  " Go forward two lists
208  Xnewer
209  let l = g:Xgetlist()
210  call assert_equal('Line3', l[0].text)
211
212  " Test for the optional count argument
213  Xolder 2
214  let l = g:Xgetlist()
215  call assert_equal('Line1', l[0].text)
216
217  Xnewer 2
218  let l = g:Xgetlist()
219  call assert_equal('Line3', l[0].text)
220endfunc
221
222func Test_cage()
223  call XageTests('c')
224  call XageTests('l')
225endfunc
226
227" Tests for the :cwindow, :lwindow :cclose, :lclose, :copen and :lopen
228" commands
229func XwindowTests(cchar)
230  call s:setup_commands(a:cchar)
231
232  " Opening the location list window without any errors should fail
233  if a:cchar == 'l'
234      call assert_fails('lopen', 'E776:')
235  endif
236
237  " Create a list with no valid entries
238  Xgetexpr ['non-error 1', 'non-error 2', 'non-error 3']
239
240  " Quickfix/Location window should not open with no valid errors
241  Xwindow
242  call assert_true(winnr('$') == 1)
243
244  " Create a list with valid entries
245  Xgetexpr ['Xtestfile1:1:3:Line1', 'Xtestfile2:2:2:Line2',
246		  \ 'Xtestfile3:3:1:Line3']
247
248  " Open the window
249  Xwindow
250  call assert_true(winnr('$') == 2 && winnr() == 2 &&
251	\ getline('.') ==# 'Xtestfile1|1 col 3| Line1')
252  redraw!
253
254  " Close the window
255  Xclose
256  call assert_true(winnr('$') == 1)
257
258  " Create a list with no valid entries
259  Xgetexpr ['non-error 1', 'non-error 2', 'non-error 3']
260
261  " Open the window
262  Xopen 5
263  call assert_true(winnr('$') == 2 && getline('.') ==# '|| non-error 1'
264		      \  && winheight('.') == 5)
265
266  " Opening the window again, should move the cursor to that window
267  wincmd t
268  Xopen 7
269  call assert_true(winnr('$') == 2 && winnr() == 2 &&
270	\ winheight('.') == 7 &&
271	\ getline('.') ==# '|| non-error 1')
272
273  " :cnext in quickfix window should move to the next entry
274  Xnext
275  call assert_equal(2, g:Xgetlist({'idx' : 0}).idx)
276
277  " Calling cwindow should close the quickfix window with no valid errors
278  Xwindow
279  call assert_true(winnr('$') == 1)
280
281  " Specifying the width should adjust the width for a vertically split
282  " quickfix window.
283  vert Xopen
284  call assert_equal(10, winwidth(0))
285  vert Xopen 12
286  call assert_equal(12, winwidth(0))
287  Xclose
288
289  " Horizontally or vertically splitting the quickfix window should create a
290  " normal window/buffer
291  Xopen
292  wincmd s
293  call assert_equal(0, getwininfo(win_getid())[0].quickfix)
294  call assert_equal(0, getwininfo(win_getid())[0].loclist)
295  call assert_notequal('quickfix', &buftype)
296  close
297  Xopen
298  wincmd v
299  call assert_equal(0, getwininfo(win_getid())[0].quickfix)
300  call assert_equal(0, getwininfo(win_getid())[0].loclist)
301  call assert_notequal('quickfix', &buftype)
302  close
303  Xopen
304  Xclose
305
306  if a:cchar == 'c'
307      " Opening the quickfix window in multiple tab pages should reuse the
308      " quickfix buffer
309      Xgetexpr ['Xtestfile1:1:3:Line1', 'Xtestfile2:2:2:Line2',
310		  \ 'Xtestfile3:3:1:Line3']
311      Xopen
312      let qfbufnum = bufnr('%')
313      tabnew
314      Xopen
315      call assert_equal(qfbufnum, bufnr('%'))
316      new | only | tabonly
317  endif
318endfunc
319
320func Test_cwindow()
321  call XwindowTests('c')
322  call XwindowTests('l')
323endfunc
324
325func Test_copenHeight()
326  copen
327  wincmd H
328  let height = winheight(0)
329  copen 10
330  call assert_equal(height, winheight(0))
331  quit
332endfunc
333
334func Test_copenHeight_tabline()
335  set tabline=foo showtabline=2
336  copen
337  wincmd H
338  let height = winheight(0)
339  copen 10
340  call assert_equal(height, winheight(0))
341  quit
342  set tabline& showtabline&
343endfunc
344
345
346" Tests for the :cfile, :lfile, :caddfile, :laddfile, :cgetfile and :lgetfile
347" commands.
348func XfileTests(cchar)
349  call s:setup_commands(a:cchar)
350
351  call writefile(['Xtestfile1:700:10:Line 700',
352	\ 'Xtestfile2:800:15:Line 800'], 'Xqftestfile1')
353
354  enew!
355  Xfile Xqftestfile1
356  let l = g:Xgetlist()
357  call assert_true(len(l) == 2 &&
358	\ l[0].lnum == 700 && l[0].col == 10 && l[0].text ==# 'Line 700' &&
359	\ l[1].lnum == 800 && l[1].col == 15 && l[1].text ==# 'Line 800')
360
361  " Test with a non existent file
362  call assert_fails('Xfile non_existent_file', 'E40')
363
364  " Run cfile/lfile from a modified buffer
365  enew!
366  silent! put ='Quickfix'
367  silent! Xfile Xqftestfile1
368  call assert_true(v:errmsg ==# 'E37: No write since last change (add ! to override)')
369
370  call writefile(['Xtestfile3:900:30:Line 900'], 'Xqftestfile1')
371  Xaddfile Xqftestfile1
372  let l = g:Xgetlist()
373  call assert_true(len(l) == 3 &&
374	\ l[2].lnum == 900 && l[2].col == 30 && l[2].text ==# 'Line 900')
375
376  call writefile(['Xtestfile1:222:77:Line 222',
377	\ 'Xtestfile2:333:88:Line 333'], 'Xqftestfile1')
378
379  enew!
380  Xgetfile Xqftestfile1
381  let l = g:Xgetlist()
382  call assert_true(len(l) == 2 &&
383	\ l[0].lnum == 222 && l[0].col == 77 && l[0].text ==# 'Line 222' &&
384	\ l[1].lnum == 333 && l[1].col == 88 && l[1].text ==# 'Line 333')
385
386  " Test for a file with a long line and without a newline at the end
387  let text = repeat('x', 1024)
388  let t = 'a.txt:18:' . text
389  call writefile([t], 'Xqftestfile1', 'b')
390  silent! Xfile Xqftestfile1
391  call assert_equal(text, g:Xgetlist()[0].text)
392
393  call delete('Xqftestfile1')
394endfunc
395
396func Test_cfile()
397  call XfileTests('c')
398  call XfileTests('l')
399endfunc
400
401" Tests for the :cbuffer, :lbuffer, :caddbuffer, :laddbuffer, :cgetbuffer and
402" :lgetbuffer commands.
403func XbufferTests(cchar)
404  call s:setup_commands(a:cchar)
405
406  enew!
407  silent! call setline(1, ['Xtestfile7:700:10:Line 700',
408	\ 'Xtestfile8:800:15:Line 800'])
409  Xbuffer!
410  let l = g:Xgetlist()
411  call assert_true(len(l) == 2 &&
412	\ l[0].lnum == 700 && l[0].col == 10 && l[0].text ==# 'Line 700' &&
413	\ l[1].lnum == 800 && l[1].col == 15 && l[1].text ==# 'Line 800')
414
415  enew!
416  silent! call setline(1, ['Xtestfile9:900:55:Line 900',
417	\ 'Xtestfile10:950:66:Line 950'])
418  Xgetbuffer
419  let l = g:Xgetlist()
420  call assert_true(len(l) == 2 &&
421	\ l[0].lnum == 900 && l[0].col == 55 && l[0].text ==# 'Line 900' &&
422	\ l[1].lnum == 950 && l[1].col == 66 && l[1].text ==# 'Line 950')
423
424  enew!
425  silent! call setline(1, ['Xtestfile11:700:20:Line 700',
426	\ 'Xtestfile12:750:25:Line 750'])
427  Xaddbuffer
428  let l = g:Xgetlist()
429  call assert_true(len(l) == 4 &&
430	\ l[1].lnum == 950 && l[1].col == 66 && l[1].text ==# 'Line 950' &&
431	\ l[2].lnum == 700 && l[2].col == 20 && l[2].text ==# 'Line 700' &&
432	\ l[3].lnum == 750 && l[3].col == 25 && l[3].text ==# 'Line 750')
433  enew!
434
435  " Check for invalid buffer
436  call assert_fails('Xbuffer 199', 'E474:')
437
438  " Check for unloaded buffer
439  edit Xtestfile1
440  let bnr = bufnr('%')
441  enew!
442  call assert_fails('Xbuffer ' . bnr, 'E681:')
443
444  " Check for invalid range
445  " Using Xbuffer will not run the range check in the cbuffer/lbuffer
446  " commands. So directly call the commands.
447  if (a:cchar == 'c')
448      call assert_fails('900,999cbuffer', 'E16:')
449  else
450      call assert_fails('900,999lbuffer', 'E16:')
451  endif
452endfunc
453
454func Test_cbuffer()
455  call XbufferTests('c')
456  call XbufferTests('l')
457endfunc
458
459func XexprTests(cchar)
460  call s:setup_commands(a:cchar)
461
462  call assert_fails('Xexpr 10', 'E777:')
463endfunc
464
465func Test_cexpr()
466  call XexprTests('c')
467  call XexprTests('l')
468endfunc
469
470" Tests for :cnext, :cprev, :cfirst, :clast commands
471func Xtest_browse(cchar)
472  call s:setup_commands(a:cchar)
473
474  call g:Xsetlist([], 'f')
475  " Jumping to first or next location list entry without any error should
476  " result in failure
477  if a:cchar == 'c'
478    let err = 'E42:'
479    let cmd = '$cc'
480  else
481    let err = 'E776:'
482    let cmd = '$ll'
483  endif
484  call assert_fails('Xnext', err)
485  call assert_fails('Xprev', err)
486  call assert_fails('Xnfile', err)
487  call assert_fails('Xpfile', err)
488  call assert_fails(cmd, err)
489
490  Xexpr ''
491  call assert_fails(cmd, 'E42:')
492
493  call s:create_test_file('Xqftestfile1')
494  call s:create_test_file('Xqftestfile2')
495
496  Xgetexpr ['Xqftestfile1:5:Line5',
497		\ 'Xqftestfile1:6:Line6',
498		\ 'Xqftestfile2:10:Line10',
499		\ 'Xqftestfile2:11:Line11',
500		\ 'RegularLine1',
501		\ 'RegularLine2']
502
503  Xfirst
504  call assert_fails('-5Xcc', 'E16:')
505  call assert_fails('Xprev', 'E553')
506  call assert_fails('Xpfile', 'E553')
507  Xnfile
508  call assert_equal('Xqftestfile2', @%)
509  call assert_equal(10, line('.'))
510  Xpfile
511  call assert_equal('Xqftestfile1', @%)
512  call assert_equal(6, line('.'))
513  5Xcc
514  call assert_equal(5, g:Xgetlist({'idx':0}).idx)
515  2Xcc
516  call assert_equal(2, g:Xgetlist({'idx':0}).idx)
517  if a:cchar == 'c'
518    cc
519  else
520    ll
521  endif
522  call assert_equal(2, g:Xgetlist({'idx':0}).idx)
523  10Xcc
524  call assert_equal(6, g:Xgetlist({'idx':0}).idx)
525  Xlast
526  Xprev
527  call assert_equal('Xqftestfile2', @%)
528  call assert_equal(11, line('.'))
529  call assert_fails('Xnext', 'E553')
530  call assert_fails('Xnfile', 'E553')
531  " To process the range using quickfix list entries, directly use the
532  " quickfix commands (don't use the user defined commands)
533  if a:cchar == 'c'
534    $cc
535  else
536    $ll
537  endif
538  call assert_equal(6, g:Xgetlist({'idx':0}).idx)
539  Xrewind
540  call assert_equal('Xqftestfile1', @%)
541  call assert_equal(5, line('.'))
542
543  10Xnext
544  call assert_equal('Xqftestfile2', @%)
545  call assert_equal(11, line('.'))
546  10Xprev
547  call assert_equal('Xqftestfile1', @%)
548  call assert_equal(5, line('.'))
549
550  " Jumping to an error from the error window using cc command
551  Xgetexpr ['Xqftestfile1:5:Line5',
552		\ 'Xqftestfile1:6:Line6',
553		\ 'Xqftestfile2:10:Line10',
554		\ 'Xqftestfile2:11:Line11']
555  Xopen
556  10Xcc
557  call assert_equal(11, line('.'))
558  call assert_equal('Xqftestfile2', @%)
559  Xopen
560  call cursor(2, 1)
561  if a:cchar == 'c'
562    .cc
563  else
564    .ll
565  endif
566  call assert_equal(6, line('.'))
567  call assert_equal('Xqftestfile1', @%)
568
569  " Jumping to an error from the error window (when only the error window is
570  " present)
571  Xopen | only
572  Xlast 1
573  call assert_equal(5, line('.'))
574  call assert_equal('Xqftestfile1', @%)
575
576  Xexpr ""
577  call assert_fails('Xnext', 'E42:')
578
579  call delete('Xqftestfile1')
580  call delete('Xqftestfile2')
581
582  " Should be able to use next/prev with invalid entries
583  Xexpr ""
584  call assert_equal(0, g:Xgetlist({'idx' : 0}).idx)
585  call assert_equal(0, g:Xgetlist({'size' : 0}).size)
586  Xaddexpr ['foo', 'bar', 'baz', 'quux', 'sh|moo']
587  call assert_equal(5, g:Xgetlist({'size' : 0}).size)
588  Xlast
589  call assert_equal(5, g:Xgetlist({'idx' : 0}).idx)
590  Xfirst
591  call assert_equal(1, g:Xgetlist({'idx' : 0}).idx)
592  2Xnext
593  call assert_equal(3, g:Xgetlist({'idx' : 0}).idx)
594endfunc
595
596func Test_browse()
597  call Xtest_browse('c')
598  call Xtest_browse('l')
599endfunc
600
601func Test_nomem()
602  call test_alloc_fail(GetAllocId('qf_dirname_start'), 0, 0)
603  call assert_fails('vimgrep vim runtest.vim', 'E342:')
604
605  call GetAllocId('qf_dirname_now')->test_alloc_fail(0, 0)
606  call assert_fails('vimgrep vim runtest.vim', 'E342:')
607
608  call test_alloc_fail(GetAllocId('qf_namebuf'), 0, 0)
609  call assert_fails('cfile runtest.vim', 'E342:')
610
611  call test_alloc_fail(GetAllocId('qf_errmsg'), 0, 0)
612  call assert_fails('cfile runtest.vim', 'E342:')
613
614  call test_alloc_fail(GetAllocId('qf_pattern'), 0, 0)
615  call assert_fails('cfile runtest.vim', 'E342:')
616
617endfunc
618
619func s:test_xhelpgrep(cchar)
620  call s:setup_commands(a:cchar)
621  Xhelpgrep quickfix
622  Xopen
623  if a:cchar == 'c'
624    let title_text = ':helpgrep quickfix'
625  else
626    let title_text = ':lhelpgrep quickfix'
627  endif
628  call assert_true(w:quickfix_title =~ title_text, w:quickfix_title)
629
630  " Jumping to a help topic should open the help window
631  only
632  Xnext
633  call assert_true(&buftype == 'help')
634  call assert_true(winnr('$') == 2)
635  " Jumping to the next match should reuse the help window
636  Xnext
637  call assert_true(&buftype == 'help')
638  call assert_true(winnr() == 1)
639  call assert_true(winnr('$') == 2)
640  " Jumping to the next match from the quickfix window should reuse the help
641  " window
642  Xopen
643  Xnext
644  call assert_true(&buftype == 'help')
645  call assert_true(winnr() == 1)
646  call assert_true(winnr('$') == 2)
647
648  " This wipes out the buffer, make sure that doesn't cause trouble.
649  Xclose
650
651  " When the current window is vertically split, jumping to a help match
652  " should open the help window at the top.
653  only | enew
654  let w1 = win_getid()
655  vert new
656  let w2 = win_getid()
657  Xnext
658  let w3 = win_getid()
659  call assert_true(&buftype == 'help')
660  call assert_true(winnr() == 1)
661  " See jump_to_help_window() for details
662  let w2_width = winwidth(w2)
663  if w2_width != &columns && w2_width < 80
664    call assert_equal(['col', [['leaf', w3],
665          \ ['row', [['leaf', w2], ['leaf', w1]]]]], winlayout())
666  else
667    call assert_equal(['row', [['col', [['leaf', w3], ['leaf', w2]]],
668          \ ['leaf', w1]]] , winlayout())
669  endif
670
671  new | only
672  set buftype=help
673  set modified
674  call assert_fails('Xnext', 'E37:')
675  set nomodified
676  new | only
677
678  if a:cchar == 'l'
679      " When a help window is present, running :lhelpgrep should reuse the
680      " help window and not the current window
681      new | only
682      call g:Xsetlist([], 'f')
683      help index.txt
684      wincmd w
685      lhelpgrep quickfix
686      call assert_equal(1, winnr())
687      call assert_notequal([], getloclist(1))
688      call assert_equal([], getloclist(2))
689  endif
690
691  new | only
692
693  " Search for non existing help string
694  call assert_fails('Xhelpgrep a1b2c3', 'E480:')
695  " Invalid regular expression
696  call assert_fails('Xhelpgrep \@<!', 'E866:')
697endfunc
698
699func Test_helpgrep()
700  call s:test_xhelpgrep('c')
701  helpclose
702  call s:test_xhelpgrep('l')
703endfunc
704
705func Test_errortitle()
706  augroup QfBufWinEnter
707    au!
708    au BufWinEnter * :let g:a=get(w:, 'quickfix_title', 'NONE')
709  augroup END
710  copen
711  let a=[{'lnum': 308, 'bufnr': bufnr(''), 'col': 58, 'valid': 1, 'vcol': 0, 'nr': 0, 'type': '', 'pattern': '', 'text': '    au BufWinEnter * :let g:a=get(w:, ''quickfix_title'', ''NONE'')'}]
712  call setqflist(a)
713  call assert_equal(':setqflist()', g:a)
714  augroup QfBufWinEnter
715    au!
716  augroup END
717  augroup! QfBufWinEnter
718endfunc
719
720func Test_vimgreptitle()
721  augroup QfBufWinEnter
722    au!
723    au BufWinEnter * :let g:a=get(w:, 'quickfix_title', 'NONE')
724  augroup END
725  try
726    vimgrep /pattern/j file
727  catch /E480/
728  endtry
729  copen
730  call assert_equal(':    vimgrep /pattern/j file', g:a)
731  augroup QfBufWinEnter
732    au!
733  augroup END
734  augroup! QfBufWinEnter
735endfunc
736
737func XqfTitleTests(cchar)
738  call s:setup_commands(a:cchar)
739
740  Xgetexpr ['file:1:1:message']
741  let l = g:Xgetlist()
742  if a:cchar == 'c'
743    call setqflist(l, 'r')
744  else
745    call setloclist(0, l, 'r')
746  endif
747
748  Xopen
749  if a:cchar == 'c'
750    let title = ':setqflist()'
751  else
752    let title = ':setloclist()'
753  endif
754  call assert_equal(title, w:quickfix_title)
755  Xclose
756endfunc
757
758" Tests for quickfix window's title
759func Test_qf_title()
760  call XqfTitleTests('c')
761  call XqfTitleTests('l')
762endfunc
763
764" Tests for 'errorformat'
765func Test_efm()
766  let save_efm = &efm
767  set efm=%EEEE%m,%WWWW%m,%+CCCC%.%#,%-GGGG%.%#
768  cgetexpr ['WWWW', 'EEEE', 'CCCC']
769  let l = strtrans(string(map(getqflist(), '[v:val.text, v:val.valid]')))
770  call assert_equal("[['W', 1], ['E^@CCCC', 1]]", l)
771  cgetexpr ['WWWW', 'GGGG', 'EEEE', 'CCCC']
772  let l = strtrans(string(map(getqflist(), '[v:val.text, v:val.valid]')))
773  call assert_equal("[['W', 1], ['E^@CCCC', 1]]", l)
774  cgetexpr ['WWWW', 'GGGG', 'ZZZZ', 'EEEE', 'CCCC', 'YYYY']
775  let l = strtrans(string(map(getqflist(), '[v:val.text, v:val.valid]')))
776  call assert_equal("[['W', 1], ['ZZZZ', 0], ['E^@CCCC', 1], ['YYYY', 0]]", l)
777  let &efm = save_efm
778endfunc
779
780" This will test for problems in quickfix:
781" A. incorrectly copying location lists which caused the location list to show
782"    a different name than the file that was actually being displayed.
783" B. not reusing the window for which the location list window is opened but
784"    instead creating new windows.
785" C. make sure that the location list window is not reused instead of the
786"    window it belongs to.
787"
788" Set up the test environment:
789func ReadTestProtocol(name)
790  let base = substitute(a:name, '\v^test://(.*)%(\.[^.]+)?', '\1', '')
791  let word = substitute(base, '\v(.*)\..*', '\1', '')
792
793  setl modifiable
794  setl noreadonly
795  setl noswapfile
796  setl bufhidden=delete
797  %del _
798  " For problem 2:
799  " 'buftype' has to be set to reproduce the constant opening of new windows
800  setl buftype=nofile
801
802  call setline(1, word)
803
804  setl nomodified
805  setl nomodifiable
806  setl readonly
807  exe 'doautocmd BufRead ' . substitute(a:name, '\v^test://(.*)', '\1', '')
808endfunc
809
810func Test_locationlist()
811    enew
812
813    augroup testgroup
814      au!
815      autocmd BufReadCmd test://* call ReadTestProtocol(expand("<amatch>"))
816    augroup END
817
818    let words = [ "foo", "bar", "baz", "quux", "shmoo", "spam", "eggs" ]
819
820    let qflist = []
821    for word in words
822      call add(qflist, {'filename': 'test://' . word . '.txt', 'text': 'file ' . word . '.txt', })
823      " NOTE: problem 1:
824      " intentionally not setting 'lnum' so that the quickfix entries are not
825      " valid
826      eval qflist->setloclist(0, ' ')
827    endfor
828
829    " Test A
830    lrewind
831    enew
832    lopen
833    4lnext
834    vert split
835    wincmd L
836    lopen
837    wincmd p
838    lnext
839    let fileName = expand("%")
840    wincmd p
841    let locationListFileName = substitute(getline(line('.')), '\([^|]*\)|.*', '\1', '')
842    let fileName = substitute(fileName, '\\', '/', 'g')
843    let locationListFileName = substitute(locationListFileName, '\\', '/', 'g')
844    call assert_equal("test://bar.txt", fileName)
845    call assert_equal("test://bar.txt", locationListFileName)
846
847    wincmd n | only
848
849    " Test B:
850    lrewind
851    lopen
852    2
853    exe "normal \<CR>"
854    wincmd p
855    3
856    exe "normal \<CR>"
857    wincmd p
858    4
859    exe "normal \<CR>"
860    call assert_equal(2, winnr('$'))
861    wincmd n | only
862
863    " Test C:
864    lrewind
865    lopen
866    " Let's move the location list window to the top to check whether it (the
867    " first window found) will be reused when we try to open new windows:
868    wincmd K
869    2
870    exe "normal \<CR>"
871    wincmd p
872    3
873    exe "normal \<CR>"
874    wincmd p
875    4
876    exe "normal \<CR>"
877    1wincmd w
878    call assert_equal('quickfix', &buftype)
879    2wincmd w
880    let bufferName = expand("%")
881    let bufferName = substitute(bufferName, '\\', '/', 'g')
882    call assert_equal('test://quux.txt', bufferName)
883
884    wincmd n | only
885
886    augroup! testgroup
887endfunc
888
889func Test_locationlist_curwin_was_closed()
890    augroup testgroup
891      au!
892      autocmd BufReadCmd test_curwin.txt call R(expand("<amatch>"))
893    augroup END
894
895    func! R(n)
896      quit
897    endfunc
898
899    new
900    let q = []
901    call add(q, {'filename': 'test_curwin.txt' })
902    call setloclist(0, q)
903    call assert_fails('lrewind', 'E924:')
904
905    augroup! testgroup
906endfunc
907
908func Test_locationlist_cross_tab_jump()
909  call writefile(['loclistfoo'], 'loclistfoo')
910  call writefile(['loclistbar'], 'loclistbar')
911  set switchbuf=usetab
912
913  edit loclistfoo
914  tabedit loclistbar
915  silent lgrep loclistfoo loclist*
916  call assert_equal(1, tabpagenr())
917
918  enew | only | tabonly
919  set switchbuf&vim
920  call delete('loclistfoo')
921  call delete('loclistbar')
922endfunc
923
924" More tests for 'errorformat'
925func Test_efm1()
926    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')
2363
2364    " Cannot specify both a non-empty list argument and a dict argument
2365    call assert_fails("call g:Xsetlist([{}], ' ', {})", 'E475:')
2366endfunc
2367
2368func Test_qf_property()
2369    call Xproperty_tests('c')
2370    call Xproperty_tests('l')
2371endfunc
2372
2373" Test for setting the current index in the location/quickfix list
2374func Xtest_setqfidx(cchar)
2375  call s:setup_commands(a:cchar)
2376
2377  Xgetexpr "F1:10:1:Line1\nF2:20:2:Line2\nF3:30:3:Line3"
2378  Xgetexpr "F4:10:1:Line1\nF5:20:2:Line2\nF6:30:3:Line3"
2379  Xgetexpr "F7:10:1:Line1\nF8:20:2:Line2\nF9:30:3:Line3"
2380
2381  call g:Xsetlist([], 'a', {'nr' : 3, 'idx' : 2})
2382  call g:Xsetlist([], 'a', {'nr' : 2, 'idx' : 2})
2383  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 3})
2384  Xolder 2
2385  Xopen
2386  call assert_equal(3, line('.'))
2387  Xnewer
2388  call assert_equal(2, line('.'))
2389  Xnewer
2390  call assert_equal(2, line('.'))
2391  " Update the current index with the quickfix window open
2392  wincmd w
2393  call g:Xsetlist([], 'a', {'nr' : 3, 'idx' : 3})
2394  Xopen
2395  call assert_equal(3, line('.'))
2396  Xclose
2397
2398  " Set the current index to the last entry
2399  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : '$'})
2400  call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx)
2401  " A large value should set the index to the last index
2402  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 1})
2403  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 999})
2404  call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx)
2405  " Invalid index values
2406  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : -1})
2407  call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx)
2408  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 0})
2409  call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx)
2410  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 'xx'})
2411  call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx)
2412  call assert_fails("call g:Xsetlist([], 'a', {'nr':1, 'idx':[]})", 'E745:')
2413
2414  call g:Xsetlist([], 'f')
2415  new | only
2416endfunc
2417
2418func Test_setqfidx()
2419  call Xtest_setqfidx('c')
2420  call Xtest_setqfidx('l')
2421endfunc
2422
2423" Tests for the QuickFixCmdPre/QuickFixCmdPost autocommands
2424func QfAutoCmdHandler(loc, cmd)
2425  call add(g:acmds, a:loc . a:cmd)
2426endfunc
2427
2428func Test_Autocmd()
2429  autocmd QuickFixCmdPre * call QfAutoCmdHandler('pre', expand('<amatch>'))
2430  autocmd QuickFixCmdPost * call QfAutoCmdHandler('post', expand('<amatch>'))
2431
2432  let g:acmds = []
2433  cexpr "F1:10:Line 10"
2434  caddexpr "F1:20:Line 20"
2435  cgetexpr "F1:30:Line 30"
2436  cexpr ""
2437  caddexpr ""
2438  cgetexpr ""
2439  silent! cexpr non_existing_func()
2440  silent! caddexpr non_existing_func()
2441  silent! cgetexpr non_existing_func()
2442  let l = ['precexpr',
2443	      \ 'postcexpr',
2444	      \ 'precaddexpr',
2445	      \ 'postcaddexpr',
2446	      \ 'precgetexpr',
2447	      \ 'postcgetexpr',
2448	      \ 'precexpr',
2449	      \ 'postcexpr',
2450	      \ 'precaddexpr',
2451	      \ 'postcaddexpr',
2452	      \ 'precgetexpr',
2453	      \ 'postcgetexpr',
2454	      \ 'precexpr',
2455	      \ 'precaddexpr',
2456	      \ 'precgetexpr']
2457  call assert_equal(l, g:acmds)
2458
2459  let g:acmds = []
2460  enew! | call append(0, "F2:10:Line 10")
2461  cbuffer!
2462  enew! | call append(0, "F2:20:Line 20")
2463  cgetbuffer
2464  enew! | call append(0, "F2:30:Line 30")
2465  caddbuffer
2466  new
2467  let bnum = bufnr('%')
2468  bunload
2469  exe 'silent! cbuffer! ' . bnum
2470  exe 'silent! cgetbuffer ' . bnum
2471  exe 'silent! caddbuffer ' . bnum
2472  enew!
2473  let l = ['precbuffer',
2474	      \ 'postcbuffer',
2475	      \ 'precgetbuffer',
2476	      \ 'postcgetbuffer',
2477	      \ 'precaddbuffer',
2478	      \ 'postcaddbuffer',
2479	      \ 'precbuffer',
2480	      \ 'precgetbuffer',
2481	      \ 'precaddbuffer']
2482  call assert_equal(l, g:acmds)
2483
2484  call writefile(['Xtest:1:Line1'], 'Xtest')
2485  call writefile([], 'Xempty')
2486  let g:acmds = []
2487  cfile Xtest
2488  caddfile Xtest
2489  cgetfile Xtest
2490  cfile Xempty
2491  caddfile Xempty
2492  cgetfile Xempty
2493  silent! cfile do_not_exist
2494  silent! caddfile do_not_exist
2495  silent! cgetfile do_not_exist
2496  let l = ['precfile',
2497	      \ 'postcfile',
2498	      \ 'precaddfile',
2499	      \ 'postcaddfile',
2500	      \ 'precgetfile',
2501	      \ 'postcgetfile',
2502	      \ 'precfile',
2503	      \ 'postcfile',
2504	      \ 'precaddfile',
2505	      \ 'postcaddfile',
2506	      \ 'precgetfile',
2507	      \ 'postcgetfile',
2508	      \ 'precfile',
2509	      \ 'postcfile',
2510	      \ 'precaddfile',
2511	      \ 'postcaddfile',
2512	      \ 'precgetfile',
2513	      \ 'postcgetfile']
2514  call assert_equal(l, g:acmds)
2515
2516  let g:acmds = []
2517  helpgrep quickfix
2518  silent! helpgrep non_existing_help_topic
2519  vimgrep test Xtest
2520  vimgrepadd test Xtest
2521  silent! vimgrep non_existing_test Xtest
2522  silent! vimgrepadd non_existing_test Xtest
2523  set makeprg=
2524  silent! make
2525  set makeprg&
2526  let l = ['prehelpgrep',
2527	      \ 'posthelpgrep',
2528	      \ 'prehelpgrep',
2529	      \ 'posthelpgrep',
2530	      \ 'previmgrep',
2531	      \ 'postvimgrep',
2532	      \ 'previmgrepadd',
2533	      \ 'postvimgrepadd',
2534	      \ 'previmgrep',
2535	      \ 'postvimgrep',
2536	      \ 'previmgrepadd',
2537	      \ 'postvimgrepadd',
2538	      \ 'premake',
2539	      \ 'postmake']
2540  call assert_equal(l, g:acmds)
2541
2542  if has('unix')
2543    " Run this test only on Unix-like systems. The grepprg may not be set on
2544    " non-Unix systems.
2545    " The following lines are used for the grep test. Don't remove.
2546    " Grep_Autocmd_Text: Match 1
2547    " GrepAdd_Autocmd_Text: Match 2
2548    let g:acmds = []
2549    silent grep Grep_Autocmd_Text test_quickfix.vim
2550    silent grepadd GrepAdd_Autocmd_Text test_quickfix.vim
2551    silent grep abc123def Xtest
2552    silent grepadd abc123def Xtest
2553    set grepprg=internal
2554    silent grep Grep_Autocmd_Text test_quickfix.vim
2555    silent grepadd GrepAdd_Autocmd_Text test_quickfix.vim
2556    silent lgrep Grep_Autocmd_Text test_quickfix.vim
2557    silent lgrepadd GrepAdd_Autocmd_Text test_quickfix.vim
2558    set grepprg&vim
2559    let l = ['pregrep',
2560		\ 'postgrep',
2561		\ 'pregrepadd',
2562		\ 'postgrepadd',
2563		\ 'pregrep',
2564		\ 'postgrep',
2565		\ 'pregrepadd',
2566		\ 'postgrepadd',
2567		\ 'pregrep',
2568		\ 'postgrep',
2569		\ 'pregrepadd',
2570		\ 'postgrepadd',
2571		\ 'prelgrep',
2572		\ 'postlgrep',
2573		\ 'prelgrepadd',
2574		\ 'postlgrepadd']
2575    call assert_equal(l, g:acmds)
2576  endif
2577
2578  call delete('Xtest')
2579  call delete('Xempty')
2580  au! QuickFixCmdPre
2581  au! QuickFixCmdPost
2582endfunc
2583
2584func Test_Autocmd_Exception()
2585  set efm=%m
2586  lgetexpr '?'
2587
2588  try
2589    call DoesNotExit()
2590  catch
2591    lgetexpr '1'
2592  finally
2593    lgetexpr '1'
2594  endtry
2595
2596  call assert_equal('1', getloclist(0)[0].text)
2597
2598  set efm&vim
2599endfunc
2600
2601func Test_caddbuffer_wrong()
2602  " This used to cause a memory access in freed memory.
2603  let save_efm = &efm
2604  set efm=%EEEE%m,%WWWW,%+CCCC%>%#,%GGGG%.#
2605  cgetexpr ['WWWW', 'EEEE', 'CCCC']
2606  let &efm = save_efm
2607  caddbuffer
2608  bwipe!
2609endfunc
2610
2611func Test_caddexpr_wrong()
2612  " This used to cause a memory access in freed memory.
2613  cbuffer
2614  cbuffer
2615  copen
2616  let save_efm = &efm
2617  set efm=%
2618  call assert_fails('caddexpr ""', 'E376:')
2619  let &efm = save_efm
2620endfunc
2621
2622func Test_dirstack_cleanup()
2623  " This used to cause a memory access in freed memory.
2624  let save_efm = &efm
2625  lexpr '0'
2626  lopen
2627  fun X(c)
2628    let save_efm=&efm
2629    set efm=%D%f
2630    if a:c == 'c'
2631      caddexpr '::'
2632    else
2633      laddexpr ':0:0'
2634    endif
2635    let &efm=save_efm
2636  endfun
2637  call X('c')
2638  call X('l')
2639  call setqflist([], 'r')
2640  caddbuffer
2641  let &efm = save_efm
2642endfunc
2643
2644" Tests for jumping to entries from the location list window and quickfix
2645" window
2646func Test_cwindow_jump()
2647  set efm=%f%%%l%%%m
2648  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2649  lopen | only
2650  lfirst
2651  call assert_true(winnr('$') == 2)
2652  call assert_true(winnr() == 1)
2653  " Location list for the new window should be set
2654  call assert_true(getloclist(0)[2].text == 'Line 30')
2655
2656  " Open a scratch buffer
2657  " Open a new window and create a location list
2658  " Open the location list window and close the other window
2659  " Jump to an entry.
2660  " Should create a new window and jump to the entry. The scratch buffer
2661  " should not be used.
2662  enew | only
2663  set buftype=nofile
2664  below new
2665  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2666  lopen
2667  2wincmd c
2668  lnext
2669  call assert_true(winnr('$') == 3)
2670  call assert_true(winnr() == 2)
2671
2672  " Open two windows with two different location lists
2673  " Open the location list window and close the previous window
2674  " Jump to an entry in the location list window
2675  " Should open the file in the first window and not set the location list.
2676  enew | only
2677  lgetexpr ["F1%5%Line 5"]
2678  below new
2679  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2680  lopen
2681  2wincmd c
2682  lnext
2683  call assert_true(winnr() == 1)
2684  call assert_true(getloclist(0)[0].text == 'Line 5')
2685
2686  enew | only
2687  cgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2688  copen
2689  cnext
2690  call assert_true(winnr('$') == 2)
2691  call assert_true(winnr() == 1)
2692
2693  " open the quickfix buffer in two windows and jump to an entry. Should open
2694  " the file in the first quickfix window.
2695  enew | only
2696  copen
2697  let bnum = bufnr('')
2698  exe 'sbuffer ' . bnum
2699  wincmd b
2700  cfirst
2701  call assert_equal(2, winnr())
2702  call assert_equal('F1', @%)
2703  enew | only
2704  exe 'sb' bnum
2705  exe 'botright sb' bnum
2706  wincmd t
2707  clast
2708  call assert_equal(2, winnr())
2709  call assert_equal('quickfix', getwinvar(1, '&buftype'))
2710  call assert_equal('quickfix', getwinvar(3, '&buftype'))
2711
2712  " Jumping to a file from the location list window should find a usable
2713  " window by wrapping around the window list.
2714  enew | only
2715  call setloclist(0, [], 'f')
2716  new | new
2717  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2718  lopen
2719  1close
2720  call assert_equal(0, getloclist(3, {'id' : 0}).id)
2721  lnext
2722  call assert_equal(3, winnr())
2723  call assert_equal(getloclist(1, {'id' : 0}).id, getloclist(3, {'id' : 0}).id)
2724
2725  enew | only
2726  set efm&vim
2727endfunc
2728
2729func Test_cwindow_highlight()
2730  CheckScreendump
2731
2732  let lines =<< trim END
2733	call setline(1, ['some', 'text', 'with', 'matches'])
2734	write XCwindow
2735	vimgrep e XCwindow
2736	redraw
2737	cwindow 4
2738  END
2739  call writefile(lines, 'XtestCwindow')
2740  let buf = RunVimInTerminal('-S XtestCwindow', #{rows: 12})
2741  call VerifyScreenDump(buf, 'Test_quickfix_cwindow_1', {})
2742
2743  call term_sendkeys(buf, ":cnext\<CR>")
2744  call VerifyScreenDump(buf, 'Test_quickfix_cwindow_2', {})
2745
2746  " clean up
2747  call StopVimInTerminal(buf)
2748  call delete('XtestCwindow')
2749  call delete('XCwindow')
2750endfunc
2751
2752func XvimgrepTests(cchar)
2753  call s:setup_commands(a:cchar)
2754
2755  call writefile(['Editor:VIM vim',
2756	      \ 'Editor:Emacs EmAcS',
2757	      \ 'Editor:Notepad NOTEPAD'], 'Xtestfile1')
2758  call writefile(['Linux', 'MacOS', 'MS-Windows'], 'Xtestfile2')
2759
2760  " Error cases
2761  call assert_fails('Xvimgrep /abc *', 'E682:')
2762
2763  let @/=''
2764  call assert_fails('Xvimgrep // *', 'E35:')
2765
2766  call assert_fails('Xvimgrep abc', 'E683:')
2767  call assert_fails('Xvimgrep a1b2c3 Xtestfile1', 'E480:')
2768  call assert_fails('Xvimgrep pat Xa1b2c3', 'E480:')
2769
2770  Xexpr ""
2771  Xvimgrepadd Notepad Xtestfile1
2772  Xvimgrepadd MacOS Xtestfile2
2773  let l = g:Xgetlist()
2774  call assert_equal(2, len(l))
2775  call assert_equal('Editor:Notepad NOTEPAD', l[0].text)
2776
2777  10Xvimgrep #\cvim#g Xtestfile?
2778  let l = g:Xgetlist()
2779  call assert_equal(2, len(l))
2780  call assert_equal(8, l[0].col)
2781  call assert_equal(12, l[1].col)
2782
2783  1Xvimgrep ?Editor? Xtestfile*
2784  let l = g:Xgetlist()
2785  call assert_equal(1, len(l))
2786  call assert_equal('Editor:VIM vim', l[0].text)
2787
2788  edit +3 Xtestfile2
2789  Xvimgrep +\cemacs+j Xtestfile1
2790  let l = g:Xgetlist()
2791  call assert_equal('Xtestfile2', @%)
2792  call assert_equal('Editor:Emacs EmAcS', l[0].text)
2793
2794  " Test for unloading a buffer after vimgrep searched the buffer
2795  %bwipe
2796  Xvimgrep /Editor/j Xtestfile*
2797  call assert_equal(0, getbufinfo('Xtestfile1')[0].loaded)
2798  call assert_equal([], getbufinfo('Xtestfile2'))
2799
2800  call delete('Xtestfile1')
2801  call delete('Xtestfile2')
2802endfunc
2803
2804" Tests for the :vimgrep command
2805func Test_vimgrep()
2806  call XvimgrepTests('c')
2807  call XvimgrepTests('l')
2808endfunc
2809
2810" Test for incsearch highlighting of the :vimgrep pattern
2811" This test used to cause "E315: ml_get: invalid lnum" errors.
2812func Test_vimgrep_incsearch()
2813  enew
2814  set incsearch
2815  call test_override("char_avail", 1)
2816
2817  call feedkeys(":2vimgrep assert test_quickfix.vim test_cdo.vim\<CR>", "ntx")
2818  let l = getqflist()
2819  call assert_equal(2, len(l))
2820
2821  call test_override("ALL", 0)
2822  set noincsearch
2823endfunc
2824
2825" Test vimgrep with the last search pattern not set
2826func Test_vimgrep_with_no_last_search_pat()
2827  let lines =<< trim [SCRIPT]
2828    call assert_fails('vimgrep // *', 'E35:')
2829    call writefile(v:errors, 'Xresult')
2830    qall!
2831  [SCRIPT]
2832  call writefile(lines, 'Xscript')
2833  if RunVim([], [], '--clean -S Xscript')
2834    call assert_equal([], readfile('Xresult'))
2835  endif
2836  call delete('Xscript')
2837  call delete('Xresult')
2838endfunc
2839
2840func Test_vimgrep_existing_swapfile()
2841  call writefile(['match apple with apple'], 'Xapple')
2842  call writefile(['swapfile'], '.Xapple.swp')
2843  let g:foundSwap = 0
2844  let g:ignoreSwapExists = 1
2845  augroup grep
2846    au SwapExists * let foundSwap = 1 | let v:swapchoice = 'e'
2847  augroup END
2848  vimgrep apple Xapple
2849  call assert_equal(1, g:foundSwap)
2850  call assert_match('.Xapple.swo', swapname(''))
2851
2852  call delete('Xapple')
2853  call delete('Xapple.swp')
2854  augroup grep
2855    au! SwapExists
2856  augroup END
2857  unlet g:ignoreSwapExists
2858endfunc
2859
2860func XfreeTests(cchar)
2861  call s:setup_commands(a:cchar)
2862
2863  enew | only
2864
2865  " Deleting the quickfix stack should work even When the current list is
2866  " somewhere in the middle of the stack
2867  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2868  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2869  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2870  Xolder
2871  call g:Xsetlist([], 'f')
2872  call assert_equal(0, len(g:Xgetlist()))
2873
2874  " After deleting the stack, adding a new list should create a stack with a
2875  " single list.
2876  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2877  call assert_equal(1, g:Xgetlist({'all':1}).nr)
2878
2879  " Deleting the stack from a quickfix window should update/clear the
2880  " quickfix/location list window.
2881  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2882  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2883  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2884  Xolder
2885  Xwindow
2886  call g:Xsetlist([], 'f')
2887  call assert_equal(2, winnr('$'))
2888  call assert_equal(1, line('$'))
2889  Xclose
2890
2891  " Deleting the stack from a non-quickfix window should update/clear the
2892  " quickfix/location list window.
2893  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2894  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2895  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2896  Xolder
2897  Xwindow
2898  wincmd p
2899  call g:Xsetlist([], 'f')
2900  call assert_equal(0, len(g:Xgetlist()))
2901  wincmd p
2902  call assert_equal(2, winnr('$'))
2903  call assert_equal(1, line('$'))
2904
2905  " After deleting the location list stack, if the location list window is
2906  " opened, then a new location list should be created. So opening the
2907  " location list window again should not create a new window.
2908  if a:cchar == 'l'
2909      lexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2910      wincmd p
2911      lopen
2912      call assert_equal(2, winnr('$'))
2913  endif
2914  Xclose
2915endfunc
2916
2917" Tests for the quickfix free functionality
2918func Test_qf_free()
2919  call XfreeTests('c')
2920  call XfreeTests('l')
2921endfunc
2922
2923" Test for buffer overflow when parsing lines and adding new entries to
2924" the quickfix list.
2925func Test_bufoverflow()
2926  set efm=%f:%l:%m
2927  cgetexpr ['File1:100:' . repeat('x', 1025)]
2928
2929  set efm=%+GCompiler:\ %.%#,%f:%l:%m
2930  cgetexpr ['Compiler: ' . repeat('a', 1015), 'File1:10:Hello World']
2931
2932  set efm=%DEntering\ directory\ %f,%f:%l:%m
2933  cgetexpr ['Entering directory ' . repeat('a', 1006),
2934	      \ 'File1:10:Hello World']
2935  set efm&vim
2936endfunc
2937
2938" Tests for getting the quickfix stack size
2939func XsizeTests(cchar)
2940  call s:setup_commands(a:cchar)
2941
2942  call g:Xsetlist([], 'f')
2943  call assert_equal(0, g:Xgetlist({'nr':'$'}).nr)
2944  call assert_equal('', g:Xgetlist({'nr':'$', 'all':1}).title)
2945  call assert_equal(0, g:Xgetlist({'nr':0}).nr)
2946
2947  Xexpr "File1:10:Line1"
2948  Xexpr "File2:20:Line2"
2949  Xexpr "File3:30:Line3"
2950  Xolder | Xolder
2951  call assert_equal(3, g:Xgetlist({'nr':'$'}).nr)
2952  call g:Xsetlist([], 'f')
2953
2954  Xexpr "File1:10:Line1"
2955  Xexpr "File2:20:Line2"
2956  Xexpr "File3:30:Line3"
2957  Xolder | Xolder
2958  call g:Xsetlist([], 'a', {'nr':'$', 'title':'Compiler'})
2959  call assert_equal('Compiler', g:Xgetlist({'nr':3, 'all':1}).title)
2960endfunc
2961
2962func Test_Qf_Size()
2963  call XsizeTests('c')
2964  call XsizeTests('l')
2965endfunc
2966
2967func Test_cclose_from_copen()
2968    augroup QF_Test
2969	au!
2970        au FileType qf :call assert_fails(':cclose', 'E788')
2971    augroup END
2972    copen
2973    augroup QF_Test
2974	au!
2975    augroup END
2976    augroup! QF_Test
2977endfunc
2978
2979func Test_cclose_in_autocmd()
2980  " Problem is only triggered if "starting" is zero, so that the OptionsSet
2981  " event will be triggered.
2982  call test_override('starting', 1)
2983  augroup QF_Test
2984    au!
2985    au FileType qf :call assert_fails(':cclose', 'E788')
2986  augroup END
2987  copen
2988  augroup QF_Test
2989    au!
2990  augroup END
2991  augroup! QF_Test
2992  call test_override('starting', 0)
2993endfunc
2994
2995" Check that ":file" without an argument is possible even when "curbuf_lock"
2996" is set.
2997func Test_file_from_copen()
2998  " Works without argument.
2999  augroup QF_Test
3000    au!
3001    au FileType qf file
3002  augroup END
3003  copen
3004
3005  augroup QF_Test
3006    au!
3007  augroup END
3008  cclose
3009
3010  " Fails with argument.
3011  augroup QF_Test
3012    au!
3013    au FileType qf call assert_fails(':file foo', 'E788')
3014  augroup END
3015  copen
3016  augroup QF_Test
3017    au!
3018  augroup END
3019  cclose
3020
3021  augroup! QF_Test
3022endfunc
3023
3024func Test_resize_from_copen()
3025    augroup QF_Test
3026	au!
3027        au FileType qf resize 5
3028    augroup END
3029    try
3030	" This should succeed without any exception.  No other buffers are
3031	" involved in the autocmd.
3032	copen
3033    finally
3034	augroup QF_Test
3035	    au!
3036	augroup END
3037	augroup! QF_Test
3038    endtry
3039endfunc
3040
3041" Tests for the quickfix buffer b:changedtick variable
3042func Xchangedtick_tests(cchar)
3043  call s:setup_commands(a:cchar)
3044
3045  new | only
3046
3047  Xexpr "" | Xexpr "" | Xexpr ""
3048
3049  Xopen
3050  Xolder
3051  Xolder
3052  Xaddexpr "F1:10:Line10"
3053  Xaddexpr "F2:20:Line20"
3054  call g:Xsetlist([{"filename":"F3", "lnum":30, "text":"Line30"}], 'a')
3055  call g:Xsetlist([], 'f')
3056  call assert_equal(8, getbufvar('%', 'changedtick'))
3057  Xclose
3058endfunc
3059
3060func Test_changedtick()
3061  call Xchangedtick_tests('c')
3062  call Xchangedtick_tests('l')
3063endfunc
3064
3065" Tests for parsing an expression using setqflist()
3066func Xsetexpr_tests(cchar)
3067  call s:setup_commands(a:cchar)
3068
3069  let t = ["File1:10:Line10", "File1:20:Line20"]
3070  call g:Xsetlist([], ' ', {'lines' : t})
3071  call g:Xsetlist([], 'a', {'lines' : ["File1:30:Line30"]})
3072
3073  let l = g:Xgetlist()
3074  call assert_equal(3, len(l))
3075  call assert_equal(20, l[1].lnum)
3076  call assert_equal('Line30', l[2].text)
3077  call g:Xsetlist([], 'r', {'lines' : ["File2:5:Line5"]})
3078  let l = g:Xgetlist()
3079  call assert_equal(1, len(l))
3080  call assert_equal('Line5', l[0].text)
3081  call assert_equal(-1, g:Xsetlist([], 'a', {'lines' : 10}))
3082  call assert_equal(-1, g:Xsetlist([], 'a', {'lines' : "F1:10:L10"}))
3083
3084  call g:Xsetlist([], 'f')
3085  " Add entries to multiple lists
3086  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["File1:10:Line10"]})
3087  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["File2:20:Line20"]})
3088  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["File1:15:Line15"]})
3089  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["File2:25:Line25"]})
3090  call assert_equal('Line15', g:Xgetlist({'nr':1, 'items':1}).items[1].text)
3091  call assert_equal('Line25', g:Xgetlist({'nr':2, 'items':1}).items[1].text)
3092
3093  " Adding entries using a custom efm
3094  set efm&
3095  call g:Xsetlist([], ' ', {'efm' : '%f#%l#%m',
3096				\ 'lines' : ["F1#10#L10", "F2#20#L20"]})
3097  call assert_equal(20, g:Xgetlist({'items':1}).items[1].lnum)
3098  call g:Xsetlist([], 'a', {'efm' : '%f#%l#%m', 'lines' : ["F3:30:L30"]})
3099  call assert_equal('F3:30:L30', g:Xgetlist({'items':1}).items[2].text)
3100  call assert_equal(20, g:Xgetlist({'items':1}).items[1].lnum)
3101  call assert_equal(-1, g:Xsetlist([], 'a', {'efm' : [],
3102				\ 'lines' : ['F1:10:L10']}))
3103endfunc
3104
3105func Test_setexpr()
3106  call Xsetexpr_tests('c')
3107  call Xsetexpr_tests('l')
3108endfunc
3109
3110" Tests for per quickfix/location list directory stack
3111func Xmultidirstack_tests(cchar)
3112  call s:setup_commands(a:cchar)
3113
3114  call g:Xsetlist([], 'f')
3115  Xexpr "" | Xexpr ""
3116
3117  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["Entering dir 'Xone/a'"]})
3118  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["Entering dir 'Xtwo/a'"]})
3119  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["one.txt:3:one one one"]})
3120  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["two.txt:5:two two two"]})
3121
3122  let l1 = g:Xgetlist({'nr':1, 'items':1})
3123  let l2 = g:Xgetlist({'nr':2, 'items':1})
3124  call assert_equal('Xone/a/one.txt', bufname(l1.items[1].bufnr))
3125  call assert_equal(3, l1.items[1].lnum)
3126  call assert_equal('Xtwo/a/two.txt', bufname(l2.items[1].bufnr))
3127  call assert_equal(5, l2.items[1].lnum)
3128endfunc
3129
3130func Test_multidirstack()
3131  call mkdir('Xone/a', 'p')
3132  call mkdir('Xtwo/a', 'p')
3133  let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7']
3134  call writefile(lines, 'Xone/a/one.txt')
3135  call writefile(lines, 'Xtwo/a/two.txt')
3136  let save_efm = &efm
3137  set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f'
3138
3139  call Xmultidirstack_tests('c')
3140  call Xmultidirstack_tests('l')
3141
3142  let &efm = save_efm
3143  call delete('Xone', 'rf')
3144  call delete('Xtwo', 'rf')
3145endfunc
3146
3147" Tests for per quickfix/location list file stack
3148func Xmultifilestack_tests(cchar)
3149  call s:setup_commands(a:cchar)
3150
3151  call g:Xsetlist([], 'f')
3152  Xexpr "" | Xexpr ""
3153
3154  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["[one.txt]"]})
3155  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["[two.txt]"]})
3156  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["(3,5) one one one"]})
3157  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["(5,9) two two two"]})
3158
3159  let l1 = g:Xgetlist({'nr':1, 'items':1})
3160  let l2 = g:Xgetlist({'nr':2, 'items':1})
3161  call assert_equal('one.txt', bufname(l1.items[1].bufnr))
3162  call assert_equal(3, l1.items[1].lnum)
3163  call assert_equal('two.txt', bufname(l2.items[1].bufnr))
3164  call assert_equal(5, l2.items[1].lnum)
3165
3166  " Test for start of a new error line in the same line where a previous
3167  " error line ends with a file stack.
3168  let efm_val = 'Error\ l%l\ in\ %f,'
3169  let efm_val .= '%-P%>(%f%r,Error\ l%l\ in\ %m,%-Q)%r'
3170  let l = g:Xgetlist({'lines' : [
3171	      \ '(one.txt',
3172	      \ 'Error l4 in one.txt',
3173	      \ ') (two.txt',
3174	      \ 'Error l6 in two.txt',
3175	      \ ')',
3176	      \ 'Error l8 in one.txt'
3177	      \ ], 'efm' : efm_val})
3178  call assert_equal(3, len(l.items))
3179  call assert_equal('one.txt', bufname(l.items[0].bufnr))
3180  call assert_equal(4, l.items[0].lnum)
3181  call assert_equal('one.txt', l.items[0].text)
3182  call assert_equal('two.txt', bufname(l.items[1].bufnr))
3183  call assert_equal(6, l.items[1].lnum)
3184  call assert_equal('two.txt', l.items[1].text)
3185  call assert_equal('one.txt', bufname(l.items[2].bufnr))
3186  call assert_equal(8, l.items[2].lnum)
3187  call assert_equal('', l.items[2].text)
3188endfunc
3189
3190func Test_multifilestack()
3191  let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7']
3192  call writefile(lines, 'one.txt')
3193  call writefile(lines, 'two.txt')
3194  let save_efm = &efm
3195  set efm=%+P[%f],(%l\\,%c)\ %m,%-Q
3196
3197  call Xmultifilestack_tests('c')
3198  call Xmultifilestack_tests('l')
3199
3200  let &efm = save_efm
3201  call delete('one.txt')
3202  call delete('two.txt')
3203endfunc
3204
3205" Tests for per buffer 'efm' setting
3206func Test_perbuf_efm()
3207  call writefile(["File1-10-Line10"], 'one.txt')
3208  call writefile(["File2#20#Line20"], 'two.txt')
3209  set efm=%f#%l#%m
3210  new | only
3211  new
3212  setlocal efm=%f-%l-%m
3213  cfile one.txt
3214  wincmd w
3215  caddfile two.txt
3216
3217  let l = getqflist()
3218  call assert_equal(10, l[0].lnum)
3219  call assert_equal('Line20', l[1].text)
3220
3221  set efm&
3222  new | only
3223  call delete('one.txt')
3224  call delete('two.txt')
3225endfunc
3226
3227" Open multiple help windows using ":lhelpgrep
3228" This test used to crash Vim
3229func Test_Multi_LL_Help()
3230    new | only
3231    lhelpgrep window
3232    lopen
3233    e#
3234    lhelpgrep buffer
3235    call assert_equal(3, winnr('$'))
3236    call assert_true(len(getloclist(1)) != 0)
3237    call assert_true(len(getloclist(2)) != 0)
3238    new | only
3239endfunc
3240
3241" Tests for adding new quickfix lists using setqflist()
3242func XaddQf_tests(cchar)
3243  call s:setup_commands(a:cchar)
3244
3245  " Create a new list using ' ' for action
3246  call g:Xsetlist([], 'f')
3247  call g:Xsetlist([], ' ', {'title' : 'Test1'})
3248  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3249  call assert_equal(1, l.nr)
3250  call assert_equal('Test1', l.title)
3251
3252  " Create a new list using ' ' for action and '$' for 'nr'
3253  call g:Xsetlist([], 'f')
3254  call g:Xsetlist([], ' ', {'title' : 'Test2', 'nr' : '$'})
3255  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3256  call assert_equal(1, l.nr)
3257  call assert_equal('Test2', l.title)
3258
3259  " Create a new list using 'a' for action
3260  call g:Xsetlist([], 'f')
3261  call g:Xsetlist([], 'a', {'title' : 'Test3'})
3262  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3263  call assert_equal(1, l.nr)
3264  call assert_equal('Test3', l.title)
3265
3266  " Create a new list using 'a' for action and '$' for 'nr'
3267  call g:Xsetlist([], 'f')
3268  call g:Xsetlist([], 'a', {'title' : 'Test3', 'nr' : '$'})
3269  call g:Xsetlist([], 'a', {'title' : 'Test4'})
3270  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3271  call assert_equal(1, l.nr)
3272  call assert_equal('Test4', l.title)
3273
3274  " Adding a quickfix list should remove all the lists following the current
3275  " list.
3276  Xexpr "" | Xexpr "" | Xexpr ""
3277  silent! 10Xolder
3278  call g:Xsetlist([], ' ', {'title' : 'Test5'})
3279  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3280  call assert_equal(2, l.nr)
3281  call assert_equal('Test5', l.title)
3282
3283  " Add a quickfix list using '$' as the list number.
3284  let lastqf = g:Xgetlist({'nr':'$'}).nr
3285  silent! 99Xolder
3286  call g:Xsetlist([], ' ', {'nr' : '$', 'title' : 'Test6'})
3287  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3288  call assert_equal(lastqf + 1, l.nr)
3289  call assert_equal('Test6', l.title)
3290
3291  " Add a quickfix list using 'nr' set to one more than the quickfix
3292  " list size.
3293  let lastqf = g:Xgetlist({'nr':'$'}).nr
3294  silent! 99Xolder
3295  call g:Xsetlist([], ' ', {'nr' : lastqf + 1, 'title' : 'Test7'})
3296  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3297  call assert_equal(lastqf + 1, l.nr)
3298  call assert_equal('Test7', l.title)
3299
3300  " Add a quickfix list to a stack with 10 lists using 'nr' set to '$'
3301  exe repeat('Xexpr "" |', 9) . 'Xexpr ""'
3302  silent! 99Xolder
3303  call g:Xsetlist([], ' ', {'nr' : '$', 'title' : 'Test8'})
3304  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3305  call assert_equal(10, l.nr)
3306  call assert_equal('Test8', l.title)
3307
3308  " Add a quickfix list using 'nr' set to a value greater than 10
3309  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : 12, 'title' : 'Test9'}))
3310
3311  " Try adding a quickfix list with 'nr' set to a value greater than the
3312  " quickfix list size but less than 10.
3313  call g:Xsetlist([], 'f')
3314  Xexpr "" | Xexpr "" | Xexpr ""
3315  silent! 99Xolder
3316  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : 8, 'title' : 'Test10'}))
3317
3318  " Add a quickfix list using 'nr' set to a some string or list
3319  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : [1,2], 'title' : 'Test11'}))
3320endfunc
3321
3322func Test_add_qf()
3323  call XaddQf_tests('c')
3324  call XaddQf_tests('l')
3325endfunc
3326
3327" Test for getting the quickfix list items from some text without modifying
3328" the quickfix stack
3329func XgetListFromLines(cchar)
3330  call s:setup_commands(a:cchar)
3331  call g:Xsetlist([], 'f')
3332
3333  let l = g:Xgetlist({'lines' : ["File2:20:Line20", "File2:30:Line30"]}).items
3334  call assert_equal(2, len(l))
3335  call assert_equal(30, l[1].lnum)
3336
3337  call assert_equal({}, g:Xgetlist({'lines' : 10}))
3338  call assert_equal({}, g:Xgetlist({'lines' : 'File1:10:Line10'}))
3339  call assert_equal([], g:Xgetlist({'lines' : []}).items)
3340  call assert_equal([], g:Xgetlist({'lines' : [10, 20]}).items)
3341
3342  " Parse text using a custom efm
3343  set efm&
3344  let l = g:Xgetlist({'lines':['File3#30#Line30'], 'efm' : '%f#%l#%m'}).items
3345  call assert_equal('Line30', l[0].text)
3346  let l = g:Xgetlist({'lines':['File3:30:Line30'], 'efm' : '%f-%l-%m'}).items
3347  call assert_equal('File3:30:Line30', l[0].text)
3348  let l = g:Xgetlist({'lines':['File3:30:Line30'], 'efm' : [1,2]})
3349  call assert_equal({}, l)
3350  call assert_fails("call g:Xgetlist({'lines':['abc'], 'efm':'%2'})", 'E376:')
3351  call assert_fails("call g:Xgetlist({'lines':['abc'], 'efm':''})", 'E378:')
3352
3353  " Make sure that the quickfix stack is not modified
3354  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
3355endfunc
3356
3357func Test_get_list_from_lines()
3358  call XgetListFromLines('c')
3359  call XgetListFromLines('l')
3360endfunc
3361
3362" Tests for the quickfix list id
3363func Xqfid_tests(cchar)
3364  call s:setup_commands(a:cchar)
3365
3366  call g:Xsetlist([], 'f')
3367  call assert_equal(0, g:Xgetlist({'id':0}).id)
3368  Xexpr ''
3369  let start_id = g:Xgetlist({'id' : 0}).id
3370  Xexpr '' | Xexpr ''
3371  Xolder
3372  call assert_equal(start_id, g:Xgetlist({'id':0, 'nr':1}).id)
3373  call assert_equal(start_id + 1, g:Xgetlist({'id':0, 'nr':0}).id)
3374  call assert_equal(start_id + 2, g:Xgetlist({'id':0, 'nr':'$'}).id)
3375  call assert_equal(0, g:Xgetlist({'id':0, 'nr':99}).id)
3376  call assert_equal(2, g:Xgetlist({'id':start_id + 1, 'nr':0}).nr)
3377  call assert_equal(0, g:Xgetlist({'id':99, 'nr':0}).id)
3378  call assert_equal(0, g:Xgetlist({'id':"abc", 'nr':0}).id)
3379
3380  call g:Xsetlist([], 'a', {'id':start_id, 'context':[1,2]})
3381  call assert_equal([1,2], g:Xgetlist({'nr':1, 'context':1}).context)
3382  call g:Xsetlist([], 'a', {'id':start_id+1, 'lines':['F1:10:L10']})
3383  call assert_equal('L10', g:Xgetlist({'nr':2, 'items':1}).items[0].text)
3384  call assert_equal(-1, g:Xsetlist([], 'a', {'id':999, 'title':'Vim'}))
3385  call assert_equal(-1, g:Xsetlist([], 'a', {'id':'abc', 'title':'Vim'}))
3386
3387  let qfid = g:Xgetlist({'id':0, 'nr':0})
3388  call g:Xsetlist([], 'f')
3389  call assert_equal(0, g:Xgetlist({'id':qfid, 'nr':0}).id)
3390endfunc
3391
3392func Test_qf_id()
3393  call Xqfid_tests('c')
3394  call Xqfid_tests('l')
3395endfunc
3396
3397func Xqfjump_tests(cchar)
3398  call s:setup_commands(a:cchar)
3399
3400  call writefile(["Line1\tFoo", "Line2"], 'F1')
3401  call writefile(["Line1\tBar", "Line2"], 'F2')
3402  call writefile(["Line1\tBaz", "Line2"], 'F3')
3403
3404  call g:Xsetlist([], 'f')
3405
3406  " Tests for
3407  "   Jumping to a line using a pattern
3408  "   Jumping to a column greater than the last column in a line
3409  "   Jumping to a line greater than the last line in the file
3410  let l = []
3411  for i in range(1, 7)
3412    call add(l, {})
3413  endfor
3414  let l[0].filename='F1'
3415  let l[0].pattern='Line1'
3416  let l[1].filename='F2'
3417  let l[1].pattern='Line1'
3418  let l[2].filename='F3'
3419  let l[2].pattern='Line1'
3420  let l[3].filename='F3'
3421  let l[3].lnum=1
3422  let l[3].col=9
3423  let l[3].vcol=1
3424  let l[4].filename='F3'
3425  let l[4].lnum=99
3426  let l[5].filename='F3'
3427  let l[5].lnum=1
3428  let l[5].col=99
3429  let l[5].vcol=1
3430  let l[6].filename='F3'
3431  let l[6].pattern='abcxyz'
3432
3433  call g:Xsetlist([], ' ', {'items' : l})
3434  Xopen | only
3435  2Xnext
3436  call assert_equal(3, g:Xgetlist({'idx' : 0}).idx)
3437  call assert_equal('F3', @%)
3438  Xnext
3439  call assert_equal(7, col('.'))
3440  Xnext
3441  call assert_equal(2, line('.'))
3442  Xnext
3443  call assert_equal(9, col('.'))
3444  2
3445  Xnext
3446  call assert_equal(2, line('.'))
3447
3448  if a:cchar == 'l'
3449    " When jumping to a location list entry in the location list window and
3450    " no usable windows are available, then a new window should be opened.
3451    enew! | new | only
3452    call g:Xsetlist([], 'f')
3453    setlocal buftype=nofile
3454    new
3455    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']})
3456    Xopen
3457    let winid = win_getid()
3458    wincmd p
3459    close
3460    call win_gotoid(winid)
3461    Xnext
3462    call assert_equal(3, winnr('$'))
3463    call assert_equal(1, winnr())
3464    call assert_equal(2, line('.'))
3465
3466    " When jumping to an entry in the location list window and the window
3467    " associated with the location list is not present and a window containing
3468    " the file is already present, then that window should be used.
3469    close
3470    belowright new
3471    call g:Xsetlist([], 'f')
3472    edit F3
3473    call win_gotoid(winid)
3474    Xlast
3475    call assert_equal(3, winnr())
3476    call assert_equal(6, g:Xgetlist({'size' : 1}).size)
3477    call assert_equal(winid, g:Xgetlist({'winid' : 1}).winid)
3478  endif
3479
3480  " Cleanup
3481  enew!
3482  new | only
3483
3484  call delete('F1')
3485  call delete('F2')
3486  call delete('F3')
3487endfunc
3488
3489func Test_qfjump()
3490  call Xqfjump_tests('c')
3491  call Xqfjump_tests('l')
3492endfunc
3493
3494" Tests for the getqflist() and getloclist() functions when the list is not
3495" present or is empty
3496func Xgetlist_empty_tests(cchar)
3497  call s:setup_commands(a:cchar)
3498
3499  " Empty quickfix stack
3500  call g:Xsetlist([], 'f')
3501  call assert_equal('', g:Xgetlist({'context' : 0}).context)
3502  call assert_equal(0, g:Xgetlist({'id' : 0}).id)
3503  call assert_equal(0, g:Xgetlist({'idx' : 0}).idx)
3504  call assert_equal([], g:Xgetlist({'items' : 0}).items)
3505  call assert_equal(0, g:Xgetlist({'nr' : 0}).nr)
3506  call assert_equal(0, g:Xgetlist({'size' : 0}).size)
3507  call assert_equal('', g:Xgetlist({'title' : 0}).title)
3508  call assert_equal(0, g:Xgetlist({'winid' : 0}).winid)
3509  call assert_equal(0, g:Xgetlist({'changedtick' : 0}).changedtick)
3510  if a:cchar == 'c'
3511    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0,
3512		  \ 'items' : [], 'nr' : 0, 'size' : 0, 'qfbufnr' : 0,
3513		  \ 'title' : '', 'winid' : 0, 'changedtick': 0,
3514                  \ 'quickfixtextfunc' : ''}, g:Xgetlist({'all' : 0}))
3515  else
3516    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0,
3517		\ 'items' : [], 'nr' : 0, 'size' : 0, 'title' : '',
3518		\ 'winid' : 0, 'changedtick': 0, 'filewinid' : 0,
3519		\ 'qfbufnr' : 0, 'quickfixtextfunc' : ''},
3520		\ g:Xgetlist({'all' : 0}))
3521  endif
3522
3523  " Quickfix window with empty stack
3524  silent! Xopen
3525  let qfwinid = (a:cchar == 'c') ? win_getid() : 0
3526  let qfbufnr = (a:cchar == 'c') ? bufnr('') : 0
3527  call assert_equal(qfwinid, g:Xgetlist({'winid' : 0}).winid)
3528  Xclose
3529
3530  " Empty quickfix list
3531  Xexpr ""
3532  call assert_equal('', g:Xgetlist({'context' : 0}).context)
3533  call assert_notequal(0, g:Xgetlist({'id' : 0}).id)
3534  call assert_equal(0, g:Xgetlist({'idx' : 0}).idx)
3535  call assert_equal([], g:Xgetlist({'items' : 0}).items)
3536  call assert_notequal(0, g:Xgetlist({'nr' : 0}).nr)
3537  call assert_equal(0, g:Xgetlist({'size' : 0}).size)
3538  call assert_notequal('', g:Xgetlist({'title' : 0}).title)
3539  call assert_equal(0, g:Xgetlist({'winid' : 0}).winid)
3540  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3541
3542  let qfid = g:Xgetlist({'id' : 0}).id
3543  call g:Xsetlist([], 'f')
3544
3545  " Non-existing quickfix identifier
3546  call assert_equal('', g:Xgetlist({'id' : qfid, 'context' : 0}).context)
3547  call assert_equal(0, g:Xgetlist({'id' : qfid}).id)
3548  call assert_equal(0, g:Xgetlist({'id' : qfid, 'idx' : 0}).idx)
3549  call assert_equal([], g:Xgetlist({'id' : qfid, 'items' : 0}).items)
3550  call assert_equal(0, g:Xgetlist({'id' : qfid, 'nr' : 0}).nr)
3551  call assert_equal(0, g:Xgetlist({'id' : qfid, 'size' : 0}).size)
3552  call assert_equal('', g:Xgetlist({'id' : qfid, 'title' : 0}).title)
3553  call assert_equal(0, g:Xgetlist({'id' : qfid, 'winid' : 0}).winid)
3554  call assert_equal(0, g:Xgetlist({'id' : qfid, 'changedtick' : 0}).changedtick)
3555  if a:cchar == 'c'
3556    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
3557		\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
3558		\ 'qfbufnr' : qfbufnr, 'quickfixtextfunc' : '',
3559		\ 'changedtick' : 0}, g:Xgetlist({'id' : qfid, 'all' : 0}))
3560  else
3561    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
3562		\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
3563		\ 'changedtick' : 0, 'filewinid' : 0, 'qfbufnr' : 0,
3564                \ 'quickfixtextfunc' : ''},
3565		\ g:Xgetlist({'id' : qfid, 'all' : 0}))
3566  endif
3567
3568  " Non-existing quickfix list number
3569  call assert_equal('', g:Xgetlist({'nr' : 5, 'context' : 0}).context)
3570  call assert_equal(0, g:Xgetlist({'nr' : 5}).nr)
3571  call assert_equal(0, g:Xgetlist({'nr' : 5, 'idx' : 0}).idx)
3572  call assert_equal([], g:Xgetlist({'nr' : 5, 'items' : 0}).items)
3573  call assert_equal(0, g:Xgetlist({'nr' : 5, 'id' : 0}).id)
3574  call assert_equal(0, g:Xgetlist({'nr' : 5, 'size' : 0}).size)
3575  call assert_equal('', g:Xgetlist({'nr' : 5, 'title' : 0}).title)
3576  call assert_equal(0, g:Xgetlist({'nr' : 5, 'winid' : 0}).winid)
3577  call assert_equal(0, g:Xgetlist({'nr' : 5, 'changedtick' : 0}).changedtick)
3578  if a:cchar == 'c'
3579    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
3580		\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
3581		\ 'changedtick' : 0, 'qfbufnr' : qfbufnr,
3582                \ 'quickfixtextfunc' : ''}, g:Xgetlist({'nr' : 5, 'all' : 0}))
3583  else
3584    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
3585		\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
3586		\ 'changedtick' : 0, 'filewinid' : 0, 'qfbufnr' : 0,
3587                \ 'quickfixtextfunc' : ''}, g:Xgetlist({'nr' : 5, 'all' : 0}))
3588  endif
3589endfunc
3590
3591func Test_getqflist()
3592  call Xgetlist_empty_tests('c')
3593  call Xgetlist_empty_tests('l')
3594endfunc
3595
3596func Test_getqflist_invalid_nr()
3597  " The following commands used to crash Vim
3598  cexpr ""
3599  call getqflist({'nr' : $XXX_DOES_NOT_EXIST_XXX})
3600
3601  " Cleanup
3602  call setqflist([], 'r')
3603endfunc
3604
3605" Tests for the quickfix/location list changedtick
3606func Xqftick_tests(cchar)
3607  call s:setup_commands(a:cchar)
3608
3609  call g:Xsetlist([], 'f')
3610
3611  Xexpr "F1:10:Line10"
3612  let qfid = g:Xgetlist({'id' : 0}).id
3613  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3614  Xaddexpr "F2:20:Line20\nF2:21:Line21"
3615  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
3616  call g:Xsetlist([], 'a', {'lines' : ["F3:30:Line30", "F3:31:Line31"]})
3617  call assert_equal(3, g:Xgetlist({'changedtick' : 0}).changedtick)
3618  call g:Xsetlist([], 'r', {'lines' : ["F4:40:Line40"]})
3619  call assert_equal(4, g:Xgetlist({'changedtick' : 0}).changedtick)
3620  call g:Xsetlist([], 'a', {'title' : 'New Title'})
3621  call assert_equal(5, g:Xgetlist({'changedtick' : 0}).changedtick)
3622
3623  enew!
3624  call append(0, ["F5:50:L50", "F6:60:L60"])
3625  Xaddbuffer
3626  call assert_equal(6, g:Xgetlist({'changedtick' : 0}).changedtick)
3627  enew!
3628
3629  call g:Xsetlist([], 'a', {'context' : {'bus' : 'pci'}})
3630  call assert_equal(7, g:Xgetlist({'changedtick' : 0}).changedtick)
3631  call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'},
3632	      \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], 'a')
3633  call assert_equal(8, g:Xgetlist({'changedtick' : 0}).changedtick)
3634  call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'},
3635	      \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], ' ')
3636  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3637  call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'},
3638	      \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], 'r')
3639  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
3640
3641  call writefile(["F8:80:L80", "F8:81:L81"], "Xone")
3642  Xfile Xone
3643  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3644  Xaddfile Xone
3645  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
3646
3647  " Test case for updating a non-current quickfix list
3648  call g:Xsetlist([], 'f')
3649  Xexpr "F1:1:L1"
3650  Xexpr "F2:2:L2"
3651  call g:Xsetlist([], 'a', {'nr' : 1, "lines" : ["F10:10:L10"]})
3652  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3653  call assert_equal(2, g:Xgetlist({'nr' : 1, 'changedtick' : 0}).changedtick)
3654
3655  call delete("Xone")
3656endfunc
3657
3658func Test_qf_tick()
3659  call Xqftick_tests('c')
3660  call Xqftick_tests('l')
3661endfunc
3662
3663" Test helpgrep with lang specifier
3664func Xtest_helpgrep_with_lang_specifier(cchar)
3665  call s:setup_commands(a:cchar)
3666  Xhelpgrep Vim@en
3667  call assert_equal('help', &filetype)
3668  call assert_notequal(0, g:Xgetlist({'nr' : '$'}).nr)
3669  new | only
3670endfunc
3671
3672func Test_helpgrep_with_lang_specifier()
3673  call Xtest_helpgrep_with_lang_specifier('c')
3674  call Xtest_helpgrep_with_lang_specifier('l')
3675endfunc
3676
3677" The following test used to crash Vim.
3678" Open the location list window and close the regular window associated with
3679" the location list. When the garbage collection runs now, it incorrectly
3680" marks the location list context as not in use and frees the context.
3681func Test_ll_window_ctx()
3682  call setloclist(0, [], 'f')
3683  call setloclist(0, [], 'a', {'context' : []})
3684  lopen | only
3685  call test_garbagecollect_now()
3686  echo getloclist(0, {'context' : 1}).context
3687  enew | only
3688endfunc
3689
3690" The following test used to crash vim
3691func Test_lfile_crash()
3692  sp Xtest
3693  au QuickFixCmdPre * bw
3694  call assert_fails('lfile', 'E40')
3695  au! QuickFixCmdPre
3696endfunc
3697
3698" The following test used to crash vim
3699func Test_lbuffer_crash()
3700  sv Xtest
3701  augroup QF_Test
3702    au!
3703    au * * bw
3704  augroup END
3705  lbuffer
3706  augroup QF_Test
3707    au!
3708  augroup END
3709endfunc
3710
3711" The following test used to crash vim
3712func Test_lexpr_crash()
3713  augroup QF_Test
3714    au!
3715    au * * call setloclist(0, [], 'f')
3716  augroup END
3717  lexpr ""
3718  augroup QF_Test
3719    au!
3720  augroup END
3721
3722  enew | only
3723  augroup QF_Test
3724    au!
3725    au BufNew * call setloclist(0, [], 'f')
3726  augroup END
3727  lexpr 'x:1:x'
3728  augroup QF_Test
3729    au!
3730  augroup END
3731
3732  enew | only
3733  lexpr ''
3734  lopen
3735  augroup QF_Test
3736    au!
3737    au FileType * call setloclist(0, [], 'f')
3738  augroup END
3739  lexpr ''
3740  augroup QF_Test
3741    au!
3742  augroup END
3743endfunc
3744
3745" The following test used to crash Vim
3746func Test_lvimgrep_crash()
3747  sv Xtest
3748  augroup QF_Test
3749    au!
3750    au * * call setloclist(0, [], 'f')
3751  augroup END
3752  lvimgrep quickfix test_quickfix.vim
3753  augroup QF_Test
3754    au!
3755  augroup END
3756
3757  new | only
3758  augroup QF_Test
3759    au!
3760    au BufEnter * call setloclist(0, [], 'r')
3761  augroup END
3762  call assert_fails('lvimgrep Test_lvimgrep_crash *', 'E926:')
3763  augroup QF_Test
3764    au!
3765  augroup END
3766
3767  enew | only
3768endfunc
3769
3770func Test_lvimgrep_crash2()
3771  au BufNewFile x sfind
3772  call assert_fails('lvimgrep x x', 'E471:')
3773  call assert_fails('lvimgrep x x x', 'E471:')
3774
3775  au! BufNewFile
3776endfunc
3777
3778" Test for the position of the quickfix and location list window
3779func Test_qfwin_pos()
3780  " Open two windows
3781  new | only
3782  new
3783  cexpr ['F1:10:L10']
3784  copen
3785  " Quickfix window should be the bottom most window
3786  call assert_equal(3, winnr())
3787  close
3788  " Open at the very top
3789  wincmd t
3790  topleft copen
3791  call assert_equal(1, winnr())
3792  close
3793  " open left of the current window
3794  wincmd t
3795  below new
3796  leftabove copen
3797  call assert_equal(2, winnr())
3798  close
3799  " open right of the current window
3800  rightbelow copen
3801  call assert_equal(3, winnr())
3802  close
3803endfunc
3804
3805" Tests for quickfix/location lists changed by autocommands when
3806" :vimgrep/:lvimgrep commands are running.
3807func Test_vimgrep_autocmd()
3808  call setqflist([], 'f')
3809  call writefile(['stars'], 'Xtest1.txt')
3810  call writefile(['stars'], 'Xtest2.txt')
3811
3812  " Test 1:
3813  " When searching for a pattern using :vimgrep, if the quickfix list is
3814  " changed by an autocmd, the results should be added to the correct quickfix
3815  " list.
3816  autocmd BufRead Xtest2.txt cexpr '' | cexpr ''
3817  silent vimgrep stars Xtest*.txt
3818  call assert_equal(1, getqflist({'nr' : 0}).nr)
3819  call assert_equal(3, getqflist({'nr' : '$'}).nr)
3820  call assert_equal('Xtest2.txt', bufname(getqflist()[1].bufnr))
3821  au! BufRead Xtest2.txt
3822
3823  " Test 2:
3824  " When searching for a pattern using :vimgrep, if the quickfix list is
3825  " freed, then a error should be given.
3826  silent! %bwipe!
3827  call setqflist([], 'f')
3828  autocmd BufRead Xtest2.txt for i in range(10) | cexpr '' | endfor
3829  call assert_fails('vimgrep stars Xtest*.txt', 'E925:')
3830  au! BufRead Xtest2.txt
3831
3832  " Test 3:
3833  " When searching for a pattern using :lvimgrep, if the location list is
3834  " freed, then the command should error out.
3835  silent! %bwipe!
3836  let g:save_winid = win_getid()
3837  autocmd BufRead Xtest2.txt call setloclist(g:save_winid, [], 'f')
3838  call assert_fails('lvimgrep stars Xtest*.txt', 'E926:')
3839  au! BufRead Xtest2.txt
3840
3841  call delete('Xtest1.txt')
3842  call delete('Xtest2.txt')
3843  call setqflist([], 'f')
3844endfunc
3845
3846" Test for an autocmd changing the current directory when running vimgrep
3847func Xvimgrep_autocmd_cd(cchar)
3848  call s:setup_commands(a:cchar)
3849
3850  %bwipe
3851  let save_cwd = getcwd()
3852
3853  augroup QF_Test
3854    au!
3855    autocmd BufRead * silent cd %:p:h
3856  augroup END
3857
3858  10Xvimgrep /vim/ Xdir/**
3859  let l = g:Xgetlist()
3860  call assert_equal('f1.txt', bufname(l[0].bufnr))
3861  call assert_equal('f2.txt', fnamemodify(bufname(l[2].bufnr), ':t'))
3862
3863  augroup QF_Test
3864    au!
3865  augroup END
3866
3867  exe 'cd ' . save_cwd
3868endfunc
3869
3870func Test_vimgrep_autocmd_cd()
3871  call mkdir('Xdir/a', 'p')
3872  call mkdir('Xdir/b', 'p')
3873  call writefile(['a_L1_vim', 'a_L2_vim'], 'Xdir/a/f1.txt')
3874  call writefile(['b_L1_vim', 'b_L2_vim'], 'Xdir/b/f2.txt')
3875  call Xvimgrep_autocmd_cd('c')
3876  call Xvimgrep_autocmd_cd('l')
3877  %bwipe
3878  call delete('Xdir', 'rf')
3879endfunc
3880
3881" The following test used to crash Vim
3882func Test_lhelpgrep_autocmd()
3883  lhelpgrep quickfix
3884  autocmd QuickFixCmdPost * call setloclist(0, [], 'f')
3885  lhelpgrep buffer
3886  call assert_equal('help', &filetype)
3887  call assert_equal(0, getloclist(0, {'nr' : '$'}).nr)
3888  lhelpgrep tabpage
3889  call assert_equal('help', &filetype)
3890  call assert_equal(1, getloclist(0, {'nr' : '$'}).nr)
3891  au! QuickFixCmdPost
3892
3893  new | only
3894  augroup QF_Test
3895    au!
3896    au BufEnter * call setqflist([], 'f')
3897  augroup END
3898  call assert_fails('helpgrep quickfix', 'E925:')
3899  augroup QF_Test
3900    au! BufEnter
3901  augroup END
3902
3903  new | only
3904  augroup QF_Test
3905    au!
3906    au BufEnter * call setqflist([], 'r')
3907  augroup END
3908  call assert_fails('helpgrep quickfix', 'E925:')
3909  augroup QF_Test
3910    au! BufEnter
3911  augroup END
3912
3913  new | only
3914  augroup QF_Test
3915    au!
3916    au BufEnter * call setloclist(0, [], 'r')
3917  augroup END
3918  call assert_fails('lhelpgrep quickfix', 'E926:')
3919  augroup QF_Test
3920    au! BufEnter
3921  augroup END
3922
3923  new | only
3924endfunc
3925
3926" Test for shortening/simplifying the file name when opening the
3927" quickfix window or when displaying the quickfix list
3928func Test_shorten_fname()
3929  if !has('unix')
3930    return
3931  endif
3932  %bwipe
3933  " Create a quickfix list with a absolute path filename
3934  let fname = getcwd() . '/test_quickfix.vim'
3935  call setqflist([], ' ', {'lines':[fname . ":20:Line20"], 'efm':'%f:%l:%m'})
3936  call assert_equal(fname, bufname('test_quickfix.vim'))
3937  " Opening the quickfix window should simplify the file path
3938  cwindow
3939  call assert_equal('test_quickfix.vim', bufname('test_quickfix.vim'))
3940  cclose
3941  %bwipe
3942  " Create a quickfix list with a absolute path filename
3943  call setqflist([], ' ', {'lines':[fname . ":20:Line20"], 'efm':'%f:%l:%m'})
3944  call assert_equal(fname, bufname('test_quickfix.vim'))
3945  " Displaying the quickfix list should simplify the file path
3946  silent! clist
3947  call assert_equal('test_quickfix.vim', bufname('test_quickfix.vim'))
3948endfunc
3949
3950" Quickfix title tests
3951" In the below tests, 'exe "cmd"' is used to invoke the quickfix commands.
3952" Otherwise due to indentation, the title is set with spaces at the beginning
3953" of the command.
3954func Test_qftitle()
3955  call writefile(["F1:1:Line1"], 'Xerr')
3956
3957  " :cexpr
3958  exe "cexpr readfile('Xerr')"
3959  call assert_equal(":cexpr readfile('Xerr')", getqflist({'title' : 1}).title)
3960
3961  " :cgetexpr
3962  exe "cgetexpr readfile('Xerr')"
3963  call assert_equal(":cgetexpr readfile('Xerr')",
3964					\ getqflist({'title' : 1}).title)
3965
3966  " :caddexpr
3967  call setqflist([], 'f')
3968  exe "caddexpr readfile('Xerr')"
3969  call assert_equal(":caddexpr readfile('Xerr')",
3970					\ getqflist({'title' : 1}).title)
3971
3972  " :cbuffer
3973  new Xerr
3974  exe "cbuffer"
3975  call assert_equal(':cbuffer (Xerr)', getqflist({'title' : 1}).title)
3976
3977  " :cgetbuffer
3978  edit Xerr
3979  exe "cgetbuffer"
3980  call assert_equal(':cgetbuffer (Xerr)', getqflist({'title' : 1}).title)
3981
3982  " :caddbuffer
3983  call setqflist([], 'f')
3984  edit Xerr
3985  exe "caddbuffer"
3986  call assert_equal(':caddbuffer (Xerr)', getqflist({'title' : 1}).title)
3987
3988  " :cfile
3989  exe "cfile Xerr"
3990  call assert_equal(':cfile Xerr', getqflist({'title' : 1}).title)
3991
3992  " :cgetfile
3993  exe "cgetfile Xerr"
3994  call assert_equal(':cgetfile Xerr', getqflist({'title' : 1}).title)
3995
3996  " :caddfile
3997  call setqflist([], 'f')
3998  exe "caddfile Xerr"
3999  call assert_equal(':caddfile Xerr', getqflist({'title' : 1}).title)
4000
4001  " :grep
4002  set grepprg=internal
4003  exe "grep F1 Xerr"
4004  call assert_equal(':grep F1 Xerr', getqflist({'title' : 1}).title)
4005
4006  " :grepadd
4007  call setqflist([], 'f')
4008  exe "grepadd F1 Xerr"
4009  call assert_equal(':grepadd F1 Xerr', getqflist({'title' : 1}).title)
4010  set grepprg&vim
4011
4012  " :vimgrep
4013  exe "vimgrep F1 Xerr"
4014  call assert_equal(':vimgrep F1 Xerr', getqflist({'title' : 1}).title)
4015
4016  " :vimgrepadd
4017  call setqflist([], 'f')
4018  exe "vimgrepadd F1 Xerr"
4019  call assert_equal(':vimgrepadd F1 Xerr', getqflist({'title' : 1}).title)
4020
4021  call setqflist(['F1:10:L10'], ' ')
4022  call assert_equal(':setqflist()', getqflist({'title' : 1}).title)
4023
4024  call setqflist([], 'f')
4025  call setqflist(['F1:10:L10'], 'a')
4026  call assert_equal(':setqflist()', getqflist({'title' : 1}).title)
4027
4028  call setqflist([], 'f')
4029  call setqflist(['F1:10:L10'], 'r')
4030  call assert_equal(':setqflist()', getqflist({'title' : 1}).title)
4031
4032  close
4033  call delete('Xerr')
4034
4035  call setqflist([], ' ', {'title' : 'Errors'})
4036  copen
4037  call assert_equal('Errors', w:quickfix_title)
4038  call setqflist([], 'r', {'items' : [{'filename' : 'a.c', 'lnum' : 10}]})
4039  call assert_equal('Errors', w:quickfix_title)
4040  cclose
4041endfunc
4042
4043func Test_lbuffer_with_bwipe()
4044  new
4045  new
4046  augroup nasty
4047    au * * bwipe
4048  augroup END
4049  lbuffer
4050  augroup nasty
4051    au!
4052  augroup END
4053endfunc
4054
4055" Test for an autocmd freeing the quickfix/location list when cexpr/lexpr is
4056" running
4057func Xexpr_acmd_freelist(cchar)
4058  call s:setup_commands(a:cchar)
4059
4060  " This was using freed memory.
4061  augroup nasty
4062    au * * call g:Xsetlist([], 'f')
4063  augroup END
4064  Xexpr "x"
4065  augroup nasty
4066    au!
4067  augroup END
4068endfunc
4069
4070func Test_cexpr_acmd_freelist()
4071  call Xexpr_acmd_freelist('c')
4072  call Xexpr_acmd_freelist('l')
4073endfunc
4074
4075" Test for commands that create a new quickfix/location list and jump to the
4076" first error automatically.
4077func Xjumpto_first_error_test(cchar)
4078  call s:setup_commands(a:cchar)
4079
4080  call s:create_test_file('Xtestfile1')
4081  call s:create_test_file('Xtestfile2')
4082  let l = ['Xtestfile1:2:Line2', 'Xtestfile2:4:Line4']
4083
4084  " Test for cexpr/lexpr
4085  enew
4086  Xexpr l
4087  call assert_equal('Xtestfile1', @%)
4088  call assert_equal(2, line('.'))
4089
4090  " Test for cfile/lfile
4091  enew
4092  call writefile(l, 'Xerr')
4093  Xfile Xerr
4094  call assert_equal('Xtestfile1', @%)
4095  call assert_equal(2, line('.'))
4096
4097  " Test for cbuffer/lbuffer
4098  edit Xerr
4099  Xbuffer
4100  call assert_equal('Xtestfile1', @%)
4101  call assert_equal(2, line('.'))
4102
4103  call delete('Xerr')
4104  call delete('Xtestfile1')
4105  call delete('Xtestfile2')
4106endfunc
4107
4108func Test_jumpto_first_error()
4109  call Xjumpto_first_error_test('c')
4110  call Xjumpto_first_error_test('l')
4111endfunc
4112
4113" Test for a quickfix autocmd changing the quickfix/location list before
4114" jumping to the first error in the new list.
4115func Xautocmd_changelist(cchar)
4116  call s:setup_commands(a:cchar)
4117
4118  " Test for cfile/lfile
4119  call s:create_test_file('Xtestfile1')
4120  call s:create_test_file('Xtestfile2')
4121  Xexpr 'Xtestfile1:2:Line2'
4122  autocmd QuickFixCmdPost * Xolder
4123  call writefile(['Xtestfile2:4:Line4'], 'Xerr')
4124  Xfile Xerr
4125  call assert_equal('Xtestfile2', @%)
4126  call assert_equal(4, line('.'))
4127  autocmd! QuickFixCmdPost
4128
4129  " Test for cbuffer/lbuffer
4130  call g:Xsetlist([], 'f')
4131  Xexpr 'Xtestfile1:2:Line2'
4132  autocmd QuickFixCmdPost * Xolder
4133  call writefile(['Xtestfile2:4:Line4'], 'Xerr')
4134  edit Xerr
4135  Xbuffer
4136  call assert_equal('Xtestfile2', @%)
4137  call assert_equal(4, line('.'))
4138  autocmd! QuickFixCmdPost
4139
4140  " Test for cexpr/lexpr
4141  call g:Xsetlist([], 'f')
4142  Xexpr 'Xtestfile1:2:Line2'
4143  autocmd QuickFixCmdPost * Xolder
4144  Xexpr 'Xtestfile2:4:Line4'
4145  call assert_equal('Xtestfile2', @%)
4146  call assert_equal(4, line('.'))
4147  autocmd! QuickFixCmdPost
4148
4149  " The grepprg may not be set on non-Unix systems
4150  if has('unix')
4151    " Test for grep/lgrep
4152    call g:Xsetlist([], 'f')
4153    Xexpr 'Xtestfile1:2:Line2'
4154    autocmd QuickFixCmdPost * Xolder
4155    silent Xgrep Line5 Xtestfile2
4156    call assert_equal('Xtestfile2', @%)
4157    call assert_equal(5, line('.'))
4158    autocmd! QuickFixCmdPost
4159  endif
4160
4161  " Test for vimgrep/lvimgrep
4162  call g:Xsetlist([], 'f')
4163  Xexpr 'Xtestfile1:2:Line2'
4164  autocmd QuickFixCmdPost * Xolder
4165  silent Xvimgrep Line5 Xtestfile2
4166  call assert_equal('Xtestfile2', @%)
4167  call assert_equal(5, line('.'))
4168  autocmd! QuickFixCmdPost
4169
4170  " Test for autocommands clearing the quickfix list before jumping to the
4171  " first error. This should not result in an error
4172  autocmd QuickFixCmdPost * call g:Xsetlist([], 'r')
4173  let v:errmsg = ''
4174  " Test for cfile/lfile
4175  Xfile Xerr
4176  call assert_true(v:errmsg !~# 'E42:')
4177  " Test for cbuffer/lbuffer
4178  edit Xerr
4179  Xbuffer
4180  call assert_true(v:errmsg !~# 'E42:')
4181  " Test for cexpr/lexpr
4182  Xexpr 'Xtestfile2:4:Line4'
4183  call assert_true(v:errmsg !~# 'E42:')
4184  " Test for grep/lgrep
4185  " The grepprg may not be set on non-Unix systems
4186  if has('unix')
4187    silent Xgrep Line5 Xtestfile2
4188    call assert_true(v:errmsg !~# 'E42:')
4189  endif
4190  " Test for vimgrep/lvimgrep
4191  call assert_fails('silent Xvimgrep Line5 Xtestfile2', 'E480:')
4192  autocmd! QuickFixCmdPost
4193
4194  call delete('Xerr')
4195  call delete('Xtestfile1')
4196  call delete('Xtestfile2')
4197endfunc
4198
4199func Test_autocmd_changelist()
4200  call Xautocmd_changelist('c')
4201  call Xautocmd_changelist('l')
4202endfunc
4203
4204" Tests for the ':filter /pat/ clist' command
4205func Test_filter_clist()
4206  cexpr ['Xfile1:10:10:Line 10', 'Xfile2:15:15:Line 15']
4207  call assert_equal([' 2 Xfile2:15 col 15: Line 15'],
4208			\ split(execute('filter /Line 15/ clist'), "\n"))
4209  call assert_equal([' 1 Xfile1:10 col 10: Line 10'],
4210			\ split(execute('filter /Xfile1/ clist'), "\n"))
4211  call assert_equal([], split(execute('filter /abc/ clist'), "\n"))
4212
4213  call setqflist([{'module' : 'abc', 'pattern' : 'pat1'},
4214			\ {'module' : 'pqr', 'pattern' : 'pat2'}], ' ')
4215  call assert_equal([' 2 pqr:pat2:  '],
4216			\ split(execute('filter /pqr/ clist'), "\n"))
4217  call assert_equal([' 1 abc:pat1:  '],
4218			\ split(execute('filter /pat1/ clist'), "\n"))
4219endfunc
4220
4221" Tests for the "CTRL-W <CR>" command.
4222func Xview_result_split_tests(cchar)
4223  call s:setup_commands(a:cchar)
4224
4225  " Test that "CTRL-W <CR>" in a qf/ll window fails with empty list.
4226  call g:Xsetlist([])
4227  Xopen
4228  let l:win_count = winnr('$')
4229  call assert_fails('execute "normal! \<C-W>\<CR>"', 'E42')
4230  call assert_equal(l:win_count, winnr('$'))
4231  Xclose
4232endfunc
4233
4234func Test_view_result_split()
4235  call Xview_result_split_tests('c')
4236  call Xview_result_split_tests('l')
4237endfunc
4238
4239" Test that :cc sets curswant
4240func Test_curswant()
4241  helpgrep quickfix
4242  normal! llll
4243  1cc
4244  call assert_equal(getcurpos()[4], virtcol('.'))
4245  cclose | helpclose
4246endfunc
4247
4248" Test for opening a file from the quickfix window using CTRL-W <Enter>
4249" doesn't leave an empty buffer around.
4250func Test_splitview()
4251  call s:create_test_file('Xtestfile1')
4252  call s:create_test_file('Xtestfile2')
4253  new | only
4254  let last_bufnr = bufnr('Test_sv_1', 1)
4255  let l = ['Xtestfile1:2:Line2', 'Xtestfile2:4:Line4']
4256  cgetexpr l
4257  copen
4258  let numbufs = len(getbufinfo())
4259  exe "normal \<C-W>\<CR>"
4260  copen
4261  exe "normal j\<C-W>\<CR>"
4262  " Make sure new empty buffers are not created
4263  call assert_equal(numbufs, len(getbufinfo()))
4264  " Creating a new buffer should use the next available buffer number
4265  call assert_equal(last_bufnr + 4, bufnr("Test_sv_2", 1))
4266  bwipe Test_sv_1
4267  bwipe Test_sv_2
4268  new | only
4269
4270  " When split opening files from location list window, make sure that two
4271  " windows doesn't refer to the same location list
4272  lgetexpr l
4273  let locid = getloclist(0, {'id' : 0}).id
4274  lopen
4275  exe "normal \<C-W>\<CR>"
4276  call assert_notequal(locid, getloclist(0, {'id' : 0}).id)
4277  call assert_equal(0, getloclist(0, {'winid' : 0}).winid)
4278  new | only
4279
4280  " When split opening files from a helpgrep location list window, a new help
4281  " window should be opened with a copy of the location list.
4282  lhelpgrep window
4283  let locid = getloclist(0, {'id' : 0}).id
4284  lwindow
4285  exe "normal j\<C-W>\<CR>"
4286  call assert_notequal(locid, getloclist(0, {'id' : 0}).id)
4287  call assert_equal(0, getloclist(0, {'winid' : 0}).winid)
4288  new | only
4289
4290  " Using :split or :vsplit from a quickfix window should behave like a :new
4291  " or a :vnew command
4292  copen
4293  split
4294  call assert_equal(3, winnr('$'))
4295  let l = getwininfo()
4296  call assert_equal([0, 0, 1], [l[0].quickfix, l[1].quickfix, l[2].quickfix])
4297  close
4298  copen
4299  vsplit
4300  let l = getwininfo()
4301  call assert_equal([0, 0, 1], [l[0].quickfix, l[1].quickfix, l[2].quickfix])
4302  new | only
4303
4304  call delete('Xtestfile1')
4305  call delete('Xtestfile2')
4306endfunc
4307
4308" Test for parsing entries using visual screen column
4309func Test_viscol()
4310  enew
4311  call writefile(["Col1\tCol2\tCol3"], 'Xfile1')
4312  edit Xfile1
4313
4314  " Use byte offset for column number
4315  set efm&
4316  cexpr "Xfile1:1:5:XX\nXfile1:1:9:YY\nXfile1:1:20:ZZ"
4317  call assert_equal([5, 8], [col('.'), virtcol('.')])
4318  cnext
4319  call assert_equal([9, 12], [col('.'), virtcol('.')])
4320  cnext
4321  call assert_equal([14, 20], [col('.'), virtcol('.')])
4322
4323  " Use screen column offset for column number
4324  set efm=%f:%l:%v:%m
4325  cexpr "Xfile1:1:8:XX\nXfile1:1:12:YY\nXfile1:1:20:ZZ"
4326  call assert_equal([5, 8], [col('.'), virtcol('.')])
4327  cnext
4328  call assert_equal([9, 12], [col('.'), virtcol('.')])
4329  cnext
4330  call assert_equal([14, 20], [col('.'), virtcol('.')])
4331  cexpr "Xfile1:1:6:XX\nXfile1:1:15:YY\nXfile1:1:24:ZZ"
4332  call assert_equal([5, 8], [col('.'), virtcol('.')])
4333  cnext
4334  call assert_equal([10, 16], [col('.'), virtcol('.')])
4335  cnext
4336  call assert_equal([14, 20], [col('.'), virtcol('.')])
4337
4338  enew
4339  call writefile(["Col1\täü\töß\tCol4"], 'Xfile1')
4340
4341  " Use byte offset for column number
4342  set efm&
4343  cexpr "Xfile1:1:8:XX\nXfile1:1:11:YY\nXfile1:1:16:ZZ"
4344  call assert_equal([8, 10], [col('.'), virtcol('.')])
4345  cnext
4346  call assert_equal([11, 17], [col('.'), virtcol('.')])
4347  cnext
4348  call assert_equal([16, 25], [col('.'), virtcol('.')])
4349
4350  " Use screen column offset for column number
4351  set efm=%f:%l:%v:%m
4352  cexpr "Xfile1:1:10:XX\nXfile1:1:17:YY\nXfile1:1:25:ZZ"
4353  call assert_equal([8, 10], [col('.'), virtcol('.')])
4354  cnext
4355  call assert_equal([11, 17], [col('.'), virtcol('.')])
4356  cnext
4357  call assert_equal([16, 25], [col('.'), virtcol('.')])
4358
4359  enew | only
4360  set efm&
4361  call delete('Xfile1')
4362endfunc
4363
4364" Test for the quickfix window buffer
4365func Xqfbuf_test(cchar)
4366  call s:setup_commands(a:cchar)
4367
4368  " Quickfix buffer should be reused across closing and opening a quickfix
4369  " window
4370  Xexpr "F1:10:Line10"
4371  Xopen
4372  let qfbnum = bufnr('')
4373  Xclose
4374  " Even after the quickfix window is closed, the buffer should be loaded
4375  call assert_true(bufloaded(qfbnum))
4376  call assert_true(qfbnum, g:Xgetlist({'qfbufnr' : 0}).qfbufnr)
4377  Xopen
4378  " Buffer should be reused when opening the window again
4379  call assert_equal(qfbnum, bufnr(''))
4380  Xclose
4381
4382  if a:cchar == 'l'
4383    %bwipe
4384    " For a location list, when both the file window and the location list
4385    " window for the list are closed, then the buffer should be freed.
4386    new | only
4387    lexpr "F1:10:Line10"
4388    let wid = win_getid()
4389    lopen
4390    let qfbnum = bufnr('')
4391    call assert_match(qfbnum . ' %a-  "\[Location List]"', execute('ls'))
4392    close
4393    " When the location list window is closed, the buffer name should not
4394    " change to 'Quickfix List'
4395    call assert_match(qfbnum . 'u h-  "\[Location List]"', execute('ls!'))
4396    call assert_true(bufloaded(qfbnum))
4397
4398    " After deleting a location list buffer using ":bdelete", opening the
4399    " location list window should mark the buffer as a location list buffer.
4400    exe "bdelete " . qfbnum
4401    lopen
4402    call assert_equal("quickfix", &buftype)
4403    call assert_equal(1, getwininfo(win_getid(winnr()))[0].loclist)
4404    call assert_equal(wid, getloclist(0, {'filewinid' : 0}).filewinid)
4405    call assert_false(&swapfile)
4406    lclose
4407
4408    " When the location list is cleared for the window, the buffer should be
4409    " removed
4410    call setloclist(0, [], 'f')
4411    call assert_false(bufexists(qfbnum))
4412    call assert_equal(0, getloclist(0, {'qfbufnr' : 0}).qfbufnr)
4413
4414    " When the location list is freed with the location list window open, the
4415    " location list buffer should not be lost. It should be reused when the
4416    " location list is again populated.
4417    lexpr "F1:10:Line10"
4418    lopen
4419    let wid = win_getid()
4420    let qfbnum = bufnr('')
4421    wincmd p
4422    call setloclist(0, [], 'f')
4423    lexpr "F1:10:Line10"
4424    lopen
4425    call assert_equal(wid, win_getid())
4426    call assert_equal(qfbnum, bufnr(''))
4427    lclose
4428
4429    " When the window with the location list is closed, the buffer should be
4430    " removed
4431    new | only
4432    call assert_false(bufexists(qfbnum))
4433  endif
4434endfunc
4435
4436func Test_qfbuf()
4437  call Xqfbuf_test('c')
4438  call Xqfbuf_test('l')
4439endfunc
4440
4441" If there is an autocmd to use only one window, then opening the location
4442" list window used to crash Vim.
4443func Test_winonly_autocmd()
4444  call s:create_test_file('Xtest1')
4445  " Autocmd to show only one Vim window at a time
4446  autocmd WinEnter * only
4447  new
4448  " Load the location list
4449  lexpr "Xtest1:5:Line5\nXtest1:10:Line10\nXtest1:15:Line15"
4450  let loclistid = getloclist(0, {'id' : 0}).id
4451  " Open the location list window. Only this window will be shown and the file
4452  " window is closed.
4453  lopen
4454  call assert_equal(loclistid, getloclist(0, {'id' : 0}).id)
4455  " Jump to an entry in the location list and make sure that the cursor is
4456  " positioned correctly.
4457  ll 3
4458  call assert_equal(loclistid, getloclist(0, {'id' : 0}).id)
4459  call assert_equal('Xtest1', @%)
4460  call assert_equal(15, line('.'))
4461  " Cleanup
4462  autocmd! WinEnter
4463  new | only
4464  call delete('Xtest1')
4465endfunc
4466
4467" Test to make sure that an empty quickfix buffer is not reused for loading
4468" a normal buffer.
4469func Test_empty_qfbuf()
4470  enew | only
4471  call writefile(["Test"], 'Xfile1')
4472  call setqflist([], 'f')
4473  copen | only
4474  let qfbuf = bufnr('')
4475  edit Xfile1
4476  call assert_notequal(qfbuf, bufnr(''))
4477  enew
4478  call delete('Xfile1')
4479endfunc
4480
4481" Test for the :cbelow, :cabove, :lbelow and :labove commands.
4482" And for the :cafter, :cbefore, :lafter and :lbefore commands.
4483func Xtest_below(cchar)
4484  call s:setup_commands(a:cchar)
4485
4486  " No quickfix/location list
4487  call assert_fails('Xbelow', 'E42:')
4488  call assert_fails('Xabove', 'E42:')
4489  call assert_fails('Xbefore', 'E42:')
4490  call assert_fails('Xafter', 'E42:')
4491
4492  " Empty quickfix/location list
4493  call g:Xsetlist([])
4494  call assert_fails('Xbelow', 'E42:')
4495  call assert_fails('Xabove', 'E42:')
4496  call assert_fails('Xbefore', 'E42:')
4497  call assert_fails('Xafter', 'E42:')
4498
4499  call s:create_test_file('X1')
4500  call s:create_test_file('X2')
4501  call s:create_test_file('X3')
4502  call s:create_test_file('X4')
4503
4504  " Invalid entries
4505  edit X1
4506  call g:Xsetlist(["E1", "E2"])
4507  call assert_fails('Xbelow', 'E42:')
4508  call assert_fails('Xabove', 'E42:')
4509  call assert_fails('3Xbelow', 'E42:')
4510  call assert_fails('4Xabove', 'E42:')
4511  call assert_fails('Xbefore', 'E42:')
4512  call assert_fails('Xafter', 'E42:')
4513  call assert_fails('3Xbefore', 'E42:')
4514  call assert_fails('4Xafter', 'E42:')
4515
4516  " Test the commands with various arguments
4517  Xexpr ["X1:5:3:L5", "X2:5:2:L5", "X2:10:3:L10", "X2:15:4:L15", "X3:3:5:L3"]
4518  edit +7 X2
4519  Xabove
4520  call assert_equal(['X2', 5], [@%, line('.')])
4521  call assert_fails('Xabove', 'E553:')
4522  normal 7G
4523  Xbefore
4524  call assert_equal(['X2', 5, 2], [@%, line('.'), col('.')])
4525  call assert_fails('Xbefore', 'E553:')
4526
4527  normal 2j
4528  Xbelow
4529  call assert_equal(['X2', 10], [@%, line('.')])
4530  normal 7G
4531  Xafter
4532  call assert_equal(['X2', 10, 3], [@%, line('.'), col('.')])
4533
4534  " Last error in this file
4535  Xbelow 99
4536  call assert_equal(['X2', 15], [@%, line('.')])
4537  call assert_fails('Xbelow', 'E553:')
4538  normal gg
4539  Xafter 99
4540  call assert_equal(['X2', 15, 4], [@%, line('.'), col('.')])
4541  call assert_fails('Xafter', 'E553:')
4542
4543  " First error in this file
4544  Xabove 99
4545  call assert_equal(['X2', 5], [@%, line('.')])
4546  call assert_fails('Xabove', 'E553:')
4547  normal G
4548  Xbefore 99
4549  call assert_equal(['X2', 5, 2], [@%, line('.'), col('.')])
4550  call assert_fails('Xbefore', 'E553:')
4551
4552  normal gg
4553  Xbelow 2
4554  call assert_equal(['X2', 10], [@%, line('.')])
4555  normal gg
4556  Xafter 2
4557  call assert_equal(['X2', 10, 3], [@%, line('.'), col('.')])
4558
4559  normal G
4560  Xabove 2
4561  call assert_equal(['X2', 10], [@%, line('.')])
4562  normal G
4563  Xbefore 2
4564  call assert_equal(['X2', 10, 3], [@%, line('.'), col('.')])
4565
4566  edit X4
4567  call assert_fails('Xabove', 'E42:')
4568  call assert_fails('Xbelow', 'E42:')
4569  call assert_fails('Xbefore', 'E42:')
4570  call assert_fails('Xafter', 'E42:')
4571  if a:cchar == 'l'
4572    " If a buffer has location list entries from some other window but not
4573    " from the current window, then the commands should fail.
4574    edit X1 | split | call setloclist(0, [], 'f')
4575    call assert_fails('Xabove', 'E776:')
4576    call assert_fails('Xbelow', 'E776:')
4577    call assert_fails('Xbefore', 'E776:')
4578    call assert_fails('Xafter', 'E776:')
4579    close
4580  endif
4581
4582  " Test for lines with multiple quickfix entries
4583  Xexpr ["X1:5:L5", "X2:5:1:L5_1", "X2:5:2:L5_2", "X2:5:3:L5_3",
4584	      \ "X2:10:1:L10_1", "X2:10:2:L10_2", "X2:10:3:L10_3",
4585	      \ "X2:15:1:L15_1", "X2:15:2:L15_2", "X2:15:3:L15_3", "X3:3:L3"]
4586  edit +1 X2
4587  Xbelow 2
4588  call assert_equal(['X2', 10, 1], [@%, line('.'), col('.')])
4589  normal 1G
4590  Xafter 2
4591  call assert_equal(['X2', 5, 2], [@%, line('.'), col('.')])
4592
4593  normal gg
4594  Xbelow 99
4595  call assert_equal(['X2', 15, 1], [@%, line('.'), col('.')])
4596  normal gg
4597  Xafter 99
4598  call assert_equal(['X2', 15, 3], [@%, line('.'), col('.')])
4599
4600  normal G
4601  Xabove 2
4602  call assert_equal(['X2', 10, 1], [@%, line('.'), col('.')])
4603  normal G
4604  Xbefore 2
4605  call assert_equal(['X2', 15, 2], [@%, line('.'), col('.')])
4606
4607  normal G
4608  Xabove 99
4609  call assert_equal(['X2', 5, 1], [@%, line('.'), col('.')])
4610  normal G
4611  Xbefore 99
4612  call assert_equal(['X2', 5, 1], [@%, line('.'), col('.')])
4613
4614  normal 10G
4615  Xabove
4616  call assert_equal(['X2', 5, 1], [@%, line('.'), col('.')])
4617  normal 10G$
4618  2Xbefore
4619  call assert_equal(['X2', 10, 2], [@%, line('.'), col('.')])
4620
4621  normal 10G
4622  Xbelow
4623  call assert_equal(['X2', 15, 1], [@%, line('.'), col('.')])
4624  normal 9G
4625  5Xafter
4626  call assert_equal(['X2', 15, 2], [@%, line('.'), col('.')])
4627
4628  " Invalid range
4629  if a:cchar == 'c'
4630    call assert_fails('-2cbelow', 'E16:')
4631    call assert_fails('-2cafter', 'E16:')
4632  else
4633    call assert_fails('-2lbelow', 'E16:')
4634    call assert_fails('-2lafter', 'E16:')
4635  endif
4636
4637  call delete('X1')
4638  call delete('X2')
4639  call delete('X3')
4640  call delete('X4')
4641endfunc
4642
4643func Test_cbelow()
4644  call Xtest_below('c')
4645  call Xtest_below('l')
4646endfunc
4647
4648func Test_quickfix_count()
4649  let commands = [
4650	\ 'cNext',
4651	\ 'cNfile',
4652	\ 'cabove',
4653	\ 'cbelow',
4654	\ 'cfirst',
4655	\ 'clast',
4656	\ 'cnewer',
4657	\ 'cnext',
4658	\ 'cnfile',
4659	\ 'colder',
4660	\ 'cprevious',
4661	\ 'crewind',
4662	\
4663	\ 'lNext',
4664	\ 'lNfile',
4665	\ 'labove',
4666	\ 'lbelow',
4667	\ 'lfirst',
4668	\ 'llast',
4669	\ 'lnewer',
4670	\ 'lnext',
4671	\ 'lnfile',
4672	\ 'lolder',
4673	\ 'lprevious',
4674	\ 'lrewind',
4675	\ ]
4676  for cmd in commands
4677    call assert_fails('-1' .. cmd, 'E16:')
4678    call assert_fails('.' .. cmd, 'E16:')
4679    call assert_fails('%' .. cmd, 'E16:')
4680    call assert_fails('$' .. cmd, 'E16:')
4681  endfor
4682endfunc
4683
4684" Test for aborting quickfix commands using QuickFixCmdPre
4685func Xtest_qfcmd_abort(cchar)
4686  call s:setup_commands(a:cchar)
4687
4688  call g:Xsetlist([], 'f')
4689
4690  " cexpr/lexpr
4691  let e = ''
4692  try
4693    Xexpr ["F1:10:Line10", "F2:20:Line20"]
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
4700  " cfile/lfile
4701  call writefile(["F1:10:Line10", "F2:20:Line20"], 'Xfile1')
4702  let e = ''
4703  try
4704    Xfile Xfile1
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  call delete('Xfile1')
4711
4712  " cgetbuffer/lgetbuffer
4713  enew!
4714  call append(0, ["F1:10:Line10", "F2:20:Line20"])
4715  let e = ''
4716  try
4717    Xgetbuffer
4718  catch /.*/
4719    let e = v:exception
4720  endtry
4721  call assert_equal('AbortCmd', e)
4722  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4723  enew!
4724
4725  " vimgrep/lvimgrep
4726  let e = ''
4727  try
4728    Xvimgrep /func/ test_quickfix.vim
4729  catch /.*/
4730    let e = v:exception
4731  endtry
4732  call assert_equal('AbortCmd', e)
4733  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4734
4735  " helpgrep/lhelpgrep
4736  let e = ''
4737  try
4738    Xhelpgrep quickfix
4739  catch /.*/
4740    let e = v:exception
4741  endtry
4742  call assert_equal('AbortCmd', e)
4743  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4744
4745  " grep/lgrep
4746  if has('unix')
4747    let e = ''
4748    try
4749      silent Xgrep func test_quickfix.vim
4750    catch /.*/
4751      let e = v:exception
4752    endtry
4753    call assert_equal('AbortCmd', e)
4754    call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4755  endif
4756endfunc
4757
4758func Test_qfcmd_abort()
4759  augroup QF_Test
4760    au!
4761    autocmd  QuickFixCmdPre * throw "AbortCmd"
4762  augroup END
4763
4764  call Xtest_qfcmd_abort('c')
4765  call Xtest_qfcmd_abort('l')
4766
4767  augroup QF_Test
4768    au!
4769  augroup END
4770endfunc
4771
4772" Test for using a file in one of the parent directories.
4773func Test_search_in_dirstack()
4774  call mkdir('Xtestdir/a/b/c', 'p')
4775  let save_cwd = getcwd()
4776  call writefile(["X1_L1", "X1_L2"], 'Xtestdir/Xfile1')
4777  call writefile(["X2_L1", "X2_L2"], 'Xtestdir/a/Xfile2')
4778  call writefile(["X3_L1", "X3_L2"], 'Xtestdir/a/b/Xfile3')
4779  call writefile(["X4_L1", "X4_L2"], 'Xtestdir/a/b/c/Xfile4')
4780
4781  let lines = "Entering dir Xtestdir\n" .
4782	      \ "Entering dir a\n" .
4783	      \ "Entering dir b\n" .
4784	      \ "Xfile2:2:X2_L2\n" .
4785	      \ "Leaving dir a\n" .
4786	      \ "Xfile1:2:X1_L2\n" .
4787	      \ "Xfile3:1:X3_L1\n" .
4788	      \ "Entering dir c\n" .
4789	      \ "Xfile4:2:X4_L2\n" .
4790	      \ "Leaving dir c\n"
4791  set efm=%DEntering\ dir\ %f,%XLeaving\ dir\ %f,%f:%l:%m
4792  cexpr lines .. "Leaving dir Xtestdir|\n" | let next = 1
4793  call assert_equal(11, getqflist({'size' : 0}).size)
4794  call assert_equal(4, getqflist({'idx' : 0}).idx)
4795  call assert_equal('X2_L2', getline('.'))
4796  call assert_equal(1, next)
4797  cnext
4798  call assert_equal(6, getqflist({'idx' : 0}).idx)
4799  call assert_equal('X1_L2', getline('.'))
4800  cnext
4801  call assert_equal(7, getqflist({'idx' : 0}).idx)
4802  call assert_equal(1, line('$'))
4803  call assert_equal('', getline(1))
4804  cnext
4805  call assert_equal(9, getqflist({'idx' : 0}).idx)
4806  call assert_equal(1, line('$'))
4807  call assert_equal('', getline(1))
4808
4809  set efm&
4810  exe 'cd ' . save_cwd
4811  call delete('Xtestdir', 'rf')
4812endfunc
4813
4814" Test for :cquit
4815func Test_cquit()
4816  " Exit Vim with a non-zero value
4817  if RunVim([], ["cquit 7"], '')
4818    call assert_equal(7, v:shell_error)
4819  endif
4820
4821  if RunVim([], ["50cquit"], '')
4822    call assert_equal(50, v:shell_error)
4823  endif
4824
4825  " Exit Vim with default value
4826  if RunVim([], ["cquit"], '')
4827    call assert_equal(1, v:shell_error)
4828  endif
4829
4830  " Exit Vim with zero value
4831  if RunVim([], ["cquit 0"], '')
4832    call assert_equal(0, v:shell_error)
4833  endif
4834
4835  " Exit Vim with negative value
4836  call assert_fails('-3cquit', 'E16:')
4837endfunc
4838
4839" Test for getting a specific item from a quickfix list
4840func Xtest_getqflist_by_idx(cchar)
4841  call s:setup_commands(a:cchar)
4842  " Empty list
4843  call assert_equal([], g:Xgetlist({'idx' : 1, 'items' : 0}).items)
4844  Xexpr ['F1:10:L10', 'F1:20:L20']
4845  let l = g:Xgetlist({'idx' : 2, 'items' : 0}).items
4846  call assert_equal(bufnr('F1'), l[0].bufnr)
4847  call assert_equal(20, l[0].lnum)
4848  call assert_equal('L20', l[0].text)
4849  call assert_equal([], g:Xgetlist({'idx' : -1, 'items' : 0}).items)
4850  call assert_equal([], g:Xgetlist({'idx' : 3, 'items' : 0}).items)
4851  %bwipe!
4852endfunc
4853
4854func Test_getqflist_by_idx()
4855  call Xtest_getqflist_by_idx('c')
4856  call Xtest_getqflist_by_idx('l')
4857endfunc
4858
4859" Test for the 'quickfixtextfunc' setting
4860func Tqfexpr(info)
4861  if a:info.quickfix
4862    let qfl = getqflist({'id' : a:info.id, 'items' : 1}).items
4863  else
4864    let qfl = getloclist(a:info.winid, {'id' : a:info.id, 'items' : 1}).items
4865  endif
4866
4867  let l = []
4868  for idx in range(a:info.start_idx - 1, a:info.end_idx - 1)
4869    let e = qfl[idx]
4870    let s = ''
4871    if e.bufnr != 0
4872      let bname = bufname(e.bufnr)
4873      let s ..= fnamemodify(bname, ':.')
4874    endif
4875    let s ..= '-'
4876    let s ..= 'L' .. string(e.lnum) .. 'C' .. string(e.col) .. '-'
4877    let s ..= e.text
4878    call add(l, s)
4879  endfor
4880
4881  return l
4882endfunc
4883
4884func Xtest_qftextfunc(cchar)
4885  call s:setup_commands(a:cchar)
4886
4887  set efm=%f:%l:%c:%m
4888  set quickfixtextfunc=Tqfexpr
4889  call assert_equal('Tqfexpr', &quickfixtextfunc)
4890  call assert_equal('',
4891        \ g:Xgetlist({'quickfixtextfunc' : 1}).quickfixtextfunc)
4892  Xexpr ['F1:10:2:green', 'F1:20:4:blue']
4893  Xwindow
4894  call assert_equal('F1-L10C2-green', getline(1))
4895  call assert_equal('F1-L20C4-blue', getline(2))
4896  Xclose
4897  set quickfixtextfunc&vim
4898  Xwindow
4899  call assert_equal('F1|10 col 2| green', getline(1))
4900  call assert_equal('F1|20 col 4| blue', getline(2))
4901  Xclose
4902  set efm&
4903  set quickfixtextfunc&
4904
4905  " Test for per list 'quickfixtextfunc' setting
4906  func PerQfText(info)
4907    if a:info.quickfix
4908      let qfl = getqflist({'id' : a:info.id, 'items' : 1}).items
4909    else
4910      let qfl = getloclist(a:info.winid, {'id' : a:info.id, 'items' : 1}).items
4911    endif
4912    if empty(qfl)
4913      return []
4914    endif
4915    let l = []
4916    for idx in range(a:info.start_idx - 1, a:info.end_idx - 1)
4917      call add(l, 'Line ' .. qfl[idx].lnum .. ', Col ' .. qfl[idx].col)
4918    endfor
4919    return l
4920  endfunc
4921  set quickfixtextfunc=Tqfexpr
4922  call g:Xsetlist([], ' ', {'quickfixtextfunc' : "PerQfText"})
4923  Xaddexpr ['F1:10:2:green', 'F1:20:4:blue']
4924  Xwindow
4925  call assert_equal('Line 10, Col 2', getline(1))
4926  call assert_equal('Line 20, Col 4', getline(2))
4927  Xclose
4928  call assert_equal(function('PerQfText'),
4929        \ g:Xgetlist({'quickfixtextfunc' : 1}).quickfixtextfunc)
4930  " Add entries to the list when the quickfix buffer is hidden
4931  Xaddexpr ['F1:30:6:red']
4932  Xwindow
4933  call assert_equal('Line 30, Col 6', getline(3))
4934  Xclose
4935  call g:Xsetlist([], 'r', {'quickfixtextfunc' : ''})
4936  call assert_equal('', g:Xgetlist({'quickfixtextfunc' : 1}).quickfixtextfunc)
4937  set quickfixtextfunc&
4938  delfunc PerQfText
4939
4940  " Non-existing function
4941  set quickfixtextfunc=Tabc
4942  call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue']", 'E117:')
4943  call assert_fails("Xwindow", 'E117:')
4944  Xclose
4945  set quickfixtextfunc&
4946
4947  " set option to a non-function
4948  set quickfixtextfunc=[10,\ 20]
4949  call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue']", 'E117:')
4950  call assert_fails("Xwindow", 'E117:')
4951  Xclose
4952  set quickfixtextfunc&
4953
4954  " set option to a function with different set of arguments
4955  func Xqftext(a, b, c)
4956    return a:a .. a:b .. a:c
4957  endfunc
4958  set quickfixtextfunc=Xqftext
4959  call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue']", 'E119:')
4960  call assert_fails("Xwindow", 'E119:')
4961  Xclose
4962
4963  " set option to a function that returns a list with non-strings
4964  func Xqftext2(d)
4965    return ['one', [], 'two']
4966  endfunc
4967  set quickfixtextfunc=Xqftext2
4968  call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue', 'F1:30:6:red']",
4969                                                                  \ 'E730:')
4970  call assert_fails('Xwindow', 'E730:')
4971  call assert_equal(['one', 'F1|20 col 4| blue', 'F1|30 col 6| red'],
4972        \ getline(1, '$'))
4973  Xclose
4974
4975  set quickfixtextfunc&
4976  delfunc Xqftext
4977  delfunc Xqftext2
4978
4979  " set the global option to a lambda function
4980  set quickfixtextfunc={d\ ->\ map(g:Xgetlist({'id'\ :\ d.id,\ 'items'\ :\ 1}).items[d.start_idx-1:d.end_idx-1],\ 'v:val.text')}
4981  Xexpr ['F1:10:2:green', 'F1:20:4:blue']
4982  Xwindow
4983  call assert_equal(['green', 'blue'], getline(1, '$'))
4984  Xclose
4985  call assert_equal("{d -> map(g:Xgetlist({'id' : d.id, 'items' : 1}).items[d.start_idx-1:d.end_idx-1], 'v:val.text')}", &quickfixtextfunc)
4986  set quickfixtextfunc&
4987
4988  " use a lambda function that returns an empty list
4989  set quickfixtextfunc={d\ ->\ []}
4990  Xexpr ['F1:10:2:green', 'F1:20:4:blue']
4991  Xwindow
4992  call assert_equal(['F1|10 col 2| green', 'F1|20 col 4| blue'],
4993        \ getline(1, '$'))
4994  Xclose
4995  set quickfixtextfunc&
4996
4997  " use a lambda function that returns a list with empty strings
4998  set quickfixtextfunc={d\ ->\ ['',\ '']}
4999  Xexpr ['F1:10:2:green', 'F1:20:4:blue']
5000  Xwindow
5001  call assert_equal(['F1|10 col 2| green', 'F1|20 col 4| blue'],
5002        \ getline(1, '$'))
5003  Xclose
5004  set quickfixtextfunc&
5005
5006  " set the per-quickfix list text function to a lambda function
5007  call g:Xsetlist([], ' ',
5008        \ {'quickfixtextfunc' :
5009        \   {d -> map(g:Xgetlist({'id' : d.id, 'items' : 1}).items[d.start_idx-1:d.end_idx-1],
5010        \ "'Line ' .. v:val.lnum .. ', Col ' .. v:val.col")}})
5011  Xaddexpr ['F1:10:2:green', 'F1:20:4:blue']
5012  Xwindow
5013  call assert_equal('Line 10, Col 2', getline(1))
5014  call assert_equal('Line 20, Col 4', getline(2))
5015  Xclose
5016  call assert_match("function('<lambda>\\d\\+')", string(g:Xgetlist({'quickfixtextfunc' : 1}).quickfixtextfunc))
5017  call g:Xsetlist([], 'f')
5018endfunc
5019
5020func Test_qftextfunc()
5021  call Xtest_qftextfunc('c')
5022  call Xtest_qftextfunc('l')
5023endfunc
5024
5025" Running :lhelpgrep command more than once in a help window, doesn't jump to
5026" the help topic
5027func Test_lhelpgrep_from_help_window()
5028  call mkdir('Xtestdir/doc', 'p')
5029  call writefile(['window'], 'Xtestdir/doc/a.txt')
5030  call writefile(['buffer'], 'Xtestdir/doc/b.txt')
5031  let save_rtp = &rtp
5032  let &rtp = 'Xtestdir'
5033  lhelpgrep window
5034  lhelpgrep buffer
5035  call assert_equal('b.txt', fnamemodify(@%, ":p:t"))
5036  lhelpgrep window
5037  call assert_equal('a.txt', fnamemodify(@%, ":p:t"))
5038  let &rtp = save_rtp
5039  call delete('Xtestdir', 'rf')
5040  new | only!
5041endfunc
5042
5043" Test for the crash fixed by 7.3.715
5044func Test_setloclist_crash()
5045  %bw!
5046  let g:BufNum = bufnr()
5047  augroup QF_Test
5048    au!
5049    au BufUnload * call setloclist(0, [{'bufnr':g:BufNum, 'lnum':1, 'col':1, 'text': 'tango down'}])
5050  augroup END
5051
5052  try
5053    lvimgrep /.*/ *.mak
5054  catch /E926:/
5055  endtry
5056  call assert_equal('tango down', getloclist(0, {'items' : 0}).items[0].text)
5057  call assert_equal(1, getloclist(0, {'size' : 0}).size)
5058
5059  augroup QF_Test
5060    au!
5061  augroup END
5062  unlet g:BufNum
5063  %bw!
5064endfunc
5065
5066" vim: shiftwidth=2 sts=2 expandtab
5067