1" Test for the quickfix feature.
2
3source check.vim
4CheckFeature quickfix
5
6set encoding=utf-8
7
8func s:setup_commands(cchar)
9  if a:cchar == 'c'
10    command! -nargs=* -bang Xlist <mods>clist<bang> <args>
11    command! -nargs=* Xgetexpr <mods>cgetexpr <args>
12    command! -nargs=* Xaddexpr <mods>caddexpr <args>
13    command! -nargs=* -count Xolder <mods><count>colder <args>
14    command! -nargs=* Xnewer <mods>cnewer <args>
15    command! -nargs=* Xopen <mods>copen <args>
16    command! -nargs=* Xwindow <mods>cwindow <args>
17    command! -nargs=* Xbottom <mods>cbottom <args>
18    command! -nargs=* Xclose <mods>cclose <args>
19    command! -nargs=* -bang Xfile <mods>cfile<bang> <args>
20    command! -nargs=* Xgetfile <mods>cgetfile <args>
21    command! -nargs=* Xaddfile <mods>caddfile <args>
22    command! -nargs=* -bang Xbuffer <mods>cbuffer<bang> <args>
23    command! -nargs=* Xgetbuffer <mods>cgetbuffer <args>
24    command! -nargs=* Xaddbuffer <mods>caddbuffer <args>
25    command! -nargs=* Xrewind <mods>crewind <args>
26    command! -count -nargs=* -bang Xnext <mods><count>cnext<bang> <args>
27    command! -count -nargs=* -bang Xprev <mods><count>cprev<bang> <args>
28    command! -nargs=* -bang Xfirst <mods>cfirst<bang> <args>
29    command! -nargs=* -bang Xlast <mods>clast<bang> <args>
30    command! -count -nargs=* -bang Xnfile <mods><count>cnfile<bang> <args>
31    command! -nargs=* -bang Xpfile <mods>cpfile<bang> <args>
32    command! -nargs=* Xexpr <mods>cexpr <args>
33    command! -range -nargs=* Xvimgrep <mods><count>vimgrep <args>
34    command! -nargs=* Xvimgrepadd <mods>vimgrepadd <args>
35    command! -nargs=* Xgrep <mods> grep <args>
36    command! -nargs=* Xgrepadd <mods> grepadd <args>
37    command! -nargs=* Xhelpgrep helpgrep <args>
38    command! -nargs=0 -count Xcc <count>cc
39    command! -count=1 -nargs=0 Xbelow <mods><count>cbelow
40    command! -count=1 -nargs=0 Xabove <mods><count>cabove
41    command! -count=1 -nargs=0 Xbefore <mods><count>cbefore
42    command! -count=1 -nargs=0 Xafter <mods><count>cafter
43    let g:Xgetlist = function('getqflist')
44    let g:Xsetlist = function('setqflist')
45    call setqflist([], 'f')
46  else
47    command! -nargs=* -bang Xlist <mods>llist<bang> <args>
48    command! -nargs=* Xgetexpr <mods>lgetexpr <args>
49    command! -nargs=* Xaddexpr <mods>laddexpr <args>
50    command! -nargs=* -count Xolder <mods><count>lolder <args>
51    command! -nargs=* Xnewer <mods>lnewer <args>
52    command! -nargs=* Xopen <mods>lopen <args>
53    command! -nargs=* Xwindow <mods>lwindow <args>
54    command! -nargs=* Xbottom <mods>lbottom <args>
55    command! -nargs=* Xclose <mods>lclose <args>
56    command! -nargs=* -bang Xfile <mods>lfile<bang> <args>
57    command! -nargs=* Xgetfile <mods>lgetfile <args>
58    command! -nargs=* Xaddfile <mods>laddfile <args>
59    command! -nargs=* -bang Xbuffer <mods>lbuffer<bang> <args>
60    command! -nargs=* Xgetbuffer <mods>lgetbuffer <args>
61    command! -nargs=* Xaddbuffer <mods>laddbuffer <args>
62    command! -nargs=* Xrewind <mods>lrewind <args>
63    command! -count -nargs=* -bang Xnext <mods><count>lnext<bang> <args>
64    command! -count -nargs=* -bang Xprev <mods><count>lprev<bang> <args>
65    command! -nargs=* -bang Xfirst <mods>lfirst<bang> <args>
66    command! -nargs=* -bang Xlast <mods>llast<bang> <args>
67    command! -count -nargs=* -bang Xnfile <mods><count>lnfile<bang> <args>
68    command! -nargs=* -bang Xpfile <mods>lpfile<bang> <args>
69    command! -nargs=* Xexpr <mods>lexpr <args>
70    command! -range -nargs=* Xvimgrep <mods><count>lvimgrep <args>
71    command! -nargs=* Xvimgrepadd <mods>lvimgrepadd <args>
72    command! -nargs=* Xgrep <mods> lgrep <args>
73    command! -nargs=* Xgrepadd <mods> lgrepadd <args>
74    command! -nargs=* Xhelpgrep lhelpgrep <args>
75    command! -nargs=0 -count Xcc <count>ll
76    command! -count=1 -nargs=0 Xbelow <mods><count>lbelow
77    command! -count=1 -nargs=0 Xabove <mods><count>labove
78    command! -count=1 -nargs=0 Xbefore <mods><count>lbefore
79    command! -count=1 -nargs=0 Xafter <mods><count>lafter
80    let g:Xgetlist = function('getloclist', [0])
81    let g:Xsetlist = function('setloclist', [0])
82    call setloclist(0, [], 'f')
83  endif
84endfunc
85
86" Tests for the :clist and :llist commands
87func XlistTests(cchar)
88  call s:setup_commands(a:cchar)
89
90  if a:cchar == 'l'
91      call assert_fails('llist', 'E776:')
92  endif
93  " With an empty list, command should return error
94  Xgetexpr []
95  silent! Xlist
96  call assert_true(v:errmsg ==# 'E42: No Errors')
97
98  " Populate the list and then try
99  Xgetexpr ['non-error 1', 'Xtestfile1:1:3:Line1',
100		  \ 'non-error 2', 'Xtestfile2:2:2:Line2',
101		  \ 'non-error 3', 'Xtestfile3:3:1:Line3']
102
103  " List only valid entries
104  let l = split(execute('Xlist', ''), "\n")
105  call assert_equal([' 2 Xtestfile1:1 col 3: Line1',
106		   \ ' 4 Xtestfile2:2 col 2: Line2',
107		   \ ' 6 Xtestfile3:3 col 1: Line3'], l)
108
109  " List all the entries
110  let l = split(execute('Xlist!', ''), "\n")
111  call assert_equal([' 1: non-error 1', ' 2 Xtestfile1:1 col 3: Line1',
112		   \ ' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2',
113		   \ ' 5: non-error 3', ' 6 Xtestfile3:3 col 1: Line3'], l)
114
115  " List a range of errors
116  let l = split(execute('Xlist 3,6', ''), "\n")
117  call assert_equal([' 4 Xtestfile2:2 col 2: Line2',
118		   \ ' 6 Xtestfile3:3 col 1: Line3'], l)
119
120  let l = split(execute('Xlist! 3,4', ''), "\n")
121  call assert_equal([' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2'], l)
122
123  let l = split(execute('Xlist -6,-4', ''), "\n")
124  call assert_equal([' 2 Xtestfile1:1 col 3: Line1'], l)
125
126  let l = split(execute('Xlist! -5,-3', ''), "\n")
127  call assert_equal([' 2 Xtestfile1:1 col 3: Line1',
128		   \ ' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2'], l)
129
130  " Test for '+'
131  let l = split(execute('Xlist! +2', ''), "\n")
132  call assert_equal([' 2 Xtestfile1:1 col 3: Line1',
133		   \ ' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2'], l)
134
135  " Different types of errors
136  call g:Xsetlist([{'lnum':10,'col':5,'type':'W', 'text':'Warning','nr':11},
137	      \ {'lnum':20,'col':10,'type':'e','text':'Error','nr':22},
138	      \ {'lnum':30,'col':15,'type':'i','text':'Info','nr':33},
139	      \ {'lnum':40,'col':20,'type':'x', 'text':'Other','nr':44},
140	      \ {'lnum':50,'col':25,'type':"\<C-A>",'text':'one','nr':55}])
141  let l = split(execute('Xlist', ""), "\n")
142  call assert_equal([' 1:10 col 5 warning  11: Warning',
143	      \ ' 2:20 col 10 error  22: Error',
144	      \ ' 3:30 col 15 info  33: Info',
145	      \ ' 4:40 col 20 x  44: Other',
146	      \ ' 5:50 col 25  55: one'], l)
147
148  " Test for module names, one needs to explicitly set `'valid':v:true` so
149  call g:Xsetlist([
150	\ {'lnum':10,'col':5,'type':'W','module':'Data.Text','text':'ModuleWarning','nr':11,'valid':v:true},
151	\ {'lnum':20,'col':10,'type':'W','module':'Data.Text','filename':'Data/Text.hs','text':'ModuleWarning','nr':22,'valid':v:true},
152	\ {'lnum':30,'col':15,'type':'W','filename':'Data/Text.hs','text':'FileWarning','nr':33,'valid':v:true}])
153  let l = split(execute('Xlist', ""), "\n")
154  call assert_equal([' 1 Data.Text:10 col 5 warning  11: ModuleWarning',
155	\ ' 2 Data.Text:20 col 10 warning  22: ModuleWarning',
156	\ ' 3 Data/Text.hs:30 col 15 warning  33: FileWarning'], l)
157
158  " Error cases
159  call assert_fails('Xlist abc', 'E488:')
160endfunc
161
162func Test_clist()
163  call XlistTests('c')
164  call XlistTests('l')
165endfunc
166
167" Tests for the :colder, :cnewer, :lolder and :lnewer commands
168" Note that this test assumes that a quickfix/location list is
169" already set by the caller.
170func XageTests(cchar)
171  call s:setup_commands(a:cchar)
172
173  if a:cchar == 'l'
174    " No location list for the current window
175    call assert_fails('lolder', 'E776:')
176    call assert_fails('lnewer', 'E776:')
177  endif
178
179  let list = [{'bufnr': bufnr('%'), 'lnum': 1}]
180  call g:Xsetlist(list)
181
182  " Jumping to a non existent list should return error
183  silent! Xolder 99
184  call assert_true(v:errmsg ==# 'E380: At bottom of quickfix stack')
185
186  silent! Xnewer 99
187  call assert_true(v:errmsg ==# 'E381: At top of quickfix stack')
188
189  " Add three quickfix/location lists
190  Xgetexpr ['Xtestfile1:1:3:Line1']
191  Xgetexpr ['Xtestfile2:2:2:Line2']
192  Xgetexpr ['Xtestfile3:3:1:Line3']
193
194  " Go back two lists
195  Xolder
196  let l = g:Xgetlist()
197  call assert_equal('Line2', l[0].text)
198
199  " Go forward two lists
200  Xnewer
201  let l = g:Xgetlist()
202  call assert_equal('Line3', l[0].text)
203
204  " Test for the optional count argument
205  Xolder 2
206  let l = g:Xgetlist()
207  call assert_equal('Line1', l[0].text)
208
209  Xnewer 2
210  let l = g:Xgetlist()
211  call assert_equal('Line3', l[0].text)
212endfunc
213
214func Test_cage()
215  call XageTests('c')
216  call XageTests('l')
217endfunc
218
219" Tests for the :cwindow, :lwindow :cclose, :lclose, :copen and :lopen
220" commands
221func XwindowTests(cchar)
222  call s:setup_commands(a:cchar)
223
224  " Opening the location list window without any errors should fail
225  if a:cchar == 'l'
226      call assert_fails('lopen', 'E776:')
227  endif
228
229  " Create a list with no valid entries
230  Xgetexpr ['non-error 1', 'non-error 2', 'non-error 3']
231
232  " Quickfix/Location window should not open with no valid errors
233  Xwindow
234  call assert_true(winnr('$') == 1)
235
236  " Create a list with valid entries
237  Xgetexpr ['Xtestfile1:1:3:Line1', 'Xtestfile2:2:2:Line2',
238		  \ 'Xtestfile3:3:1:Line3']
239
240  " Open the window
241  Xwindow
242  call assert_true(winnr('$') == 2 && winnr() == 2 &&
243	\ getline('.') ==# 'Xtestfile1|1 col 3| Line1')
244  redraw!
245
246  " Close the window
247  Xclose
248  call assert_true(winnr('$') == 1)
249
250  " Create a list with no valid entries
251  Xgetexpr ['non-error 1', 'non-error 2', 'non-error 3']
252
253  " Open the window
254  Xopen 5
255  call assert_true(winnr('$') == 2 && getline('.') ==# '|| non-error 1'
256		      \  && winheight('.') == 5)
257
258  " Opening the window again, should move the cursor to that window
259  wincmd t
260  Xopen 7
261  call assert_true(winnr('$') == 2 && winnr() == 2 &&
262	\ winheight('.') == 7 &&
263	\ getline('.') ==# '|| non-error 1')
264
265
266  " Calling cwindow should close the quickfix window with no valid errors
267  Xwindow
268  call assert_true(winnr('$') == 1)
269
270  if a:cchar == 'c'
271      " Opening the quickfix window in multiple tab pages should reuse the
272      " quickfix buffer
273      Xgetexpr ['Xtestfile1:1:3:Line1', 'Xtestfile2:2:2:Line2',
274		  \ 'Xtestfile3:3:1:Line3']
275      Xopen
276      let qfbufnum = bufnr('%')
277      tabnew
278      Xopen
279      call assert_equal(qfbufnum, bufnr('%'))
280      new | only | tabonly
281  endif
282endfunc
283
284func Test_cwindow()
285  call XwindowTests('c')
286  call XwindowTests('l')
287endfunc
288
289func Test_copenHeight()
290  copen
291  wincmd H
292  let height = winheight(0)
293  copen 10
294  call assert_equal(height, winheight(0))
295  quit
296endfunc
297
298" Tests for the :cfile, :lfile, :caddfile, :laddfile, :cgetfile and :lgetfile
299" commands.
300func XfileTests(cchar)
301  call s:setup_commands(a:cchar)
302
303  call writefile(['Xtestfile1:700:10:Line 700',
304	\ 'Xtestfile2:800:15:Line 800'], 'Xqftestfile1')
305
306  enew!
307  Xfile Xqftestfile1
308  let l = g:Xgetlist()
309  call assert_true(len(l) == 2 &&
310	\ l[0].lnum == 700 && l[0].col == 10 && l[0].text ==# 'Line 700' &&
311	\ l[1].lnum == 800 && l[1].col == 15 && l[1].text ==# 'Line 800')
312
313  " Test with a non existent file
314  call assert_fails('Xfile non_existent_file', 'E40')
315
316  " Run cfile/lfile from a modified buffer
317  enew!
318  silent! put ='Quickfix'
319  silent! Xfile Xqftestfile1
320  call assert_true(v:errmsg ==# 'E37: No write since last change (add ! to override)')
321
322  call writefile(['Xtestfile3:900:30:Line 900'], 'Xqftestfile1')
323  Xaddfile Xqftestfile1
324  let l = g:Xgetlist()
325  call assert_true(len(l) == 3 &&
326	\ l[2].lnum == 900 && l[2].col == 30 && l[2].text ==# 'Line 900')
327
328  call writefile(['Xtestfile1:222:77:Line 222',
329	\ 'Xtestfile2:333:88:Line 333'], 'Xqftestfile1')
330
331  enew!
332  Xgetfile Xqftestfile1
333  let l = g:Xgetlist()
334  call assert_true(len(l) == 2 &&
335	\ l[0].lnum == 222 && l[0].col == 77 && l[0].text ==# 'Line 222' &&
336	\ l[1].lnum == 333 && l[1].col == 88 && l[1].text ==# 'Line 333')
337
338  call delete('Xqftestfile1')
339endfunc
340
341func Test_cfile()
342  call XfileTests('c')
343  call XfileTests('l')
344endfunc
345
346" Tests for the :cbuffer, :lbuffer, :caddbuffer, :laddbuffer, :cgetbuffer and
347" :lgetbuffer commands.
348func XbufferTests(cchar)
349  call s:setup_commands(a:cchar)
350
351  enew!
352  silent! call setline(1, ['Xtestfile7:700:10:Line 700',
353	\ 'Xtestfile8:800:15:Line 800'])
354  Xbuffer!
355  let l = g:Xgetlist()
356  call assert_true(len(l) == 2 &&
357	\ l[0].lnum == 700 && l[0].col == 10 && l[0].text ==# 'Line 700' &&
358	\ l[1].lnum == 800 && l[1].col == 15 && l[1].text ==# 'Line 800')
359
360  enew!
361  silent! call setline(1, ['Xtestfile9:900:55:Line 900',
362	\ 'Xtestfile10:950:66:Line 950'])
363  Xgetbuffer
364  let l = g:Xgetlist()
365  call assert_true(len(l) == 2 &&
366	\ l[0].lnum == 900 && l[0].col == 55 && l[0].text ==# 'Line 900' &&
367	\ l[1].lnum == 950 && l[1].col == 66 && l[1].text ==# 'Line 950')
368
369  enew!
370  silent! call setline(1, ['Xtestfile11:700:20:Line 700',
371	\ 'Xtestfile12:750:25:Line 750'])
372  Xaddbuffer
373  let l = g:Xgetlist()
374  call assert_true(len(l) == 4 &&
375	\ l[1].lnum == 950 && l[1].col == 66 && l[1].text ==# 'Line 950' &&
376	\ l[2].lnum == 700 && l[2].col == 20 && l[2].text ==# 'Line 700' &&
377	\ l[3].lnum == 750 && l[3].col == 25 && l[3].text ==# 'Line 750')
378  enew!
379
380  " Check for invalid buffer
381  call assert_fails('Xbuffer 199', 'E474:')
382
383  " Check for unloaded buffer
384  edit Xtestfile1
385  let bnr = bufnr('%')
386  enew!
387  call assert_fails('Xbuffer ' . bnr, 'E681:')
388
389  " Check for invalid range
390  " Using Xbuffer will not run the range check in the cbuffer/lbuffer
391  " commands. So directly call the commands.
392  if (a:cchar == 'c')
393      call assert_fails('900,999cbuffer', 'E16:')
394  else
395      call assert_fails('900,999lbuffer', 'E16:')
396  endif
397endfunc
398
399func Test_cbuffer()
400  call XbufferTests('c')
401  call XbufferTests('l')
402endfunc
403
404func XexprTests(cchar)
405  call s:setup_commands(a:cchar)
406
407  call assert_fails('Xexpr 10', 'E777:')
408endfunc
409
410func Test_cexpr()
411  call XexprTests('c')
412  call XexprTests('l')
413endfunc
414
415" Tests for :cnext, :cprev, :cfirst, :clast commands
416func Xtest_browse(cchar)
417  call s:setup_commands(a:cchar)
418
419  call g:Xsetlist([], 'f')
420  " Jumping to first or next location list entry without any error should
421  " result in failure
422  if a:cchar == 'c'
423    let err = 'E42:'
424  else
425    let err = 'E776:'
426  endif
427  call assert_fails('Xnext', err)
428  call assert_fails('Xprev', err)
429  call assert_fails('Xnfile', err)
430  call assert_fails('Xpfile', err)
431
432  call s:create_test_file('Xqftestfile1')
433  call s:create_test_file('Xqftestfile2')
434
435  Xgetexpr ['Xqftestfile1:5:Line5',
436		\ 'Xqftestfile1:6:Line6',
437		\ 'Xqftestfile2:10:Line10',
438		\ 'Xqftestfile2:11:Line11',
439		\ 'RegularLine1',
440		\ 'RegularLine2']
441
442  Xfirst
443  call assert_fails('Xprev', 'E553')
444  call assert_fails('Xpfile', 'E553')
445  Xnfile
446  call assert_equal('Xqftestfile2', bufname('%'))
447  call assert_equal(10, line('.'))
448  Xpfile
449  call assert_equal('Xqftestfile1', bufname('%'))
450  call assert_equal(6, line('.'))
451  5Xcc
452  call assert_equal(5, g:Xgetlist({'idx':0}).idx)
453  2Xcc
454  call assert_equal(2, g:Xgetlist({'idx':0}).idx)
455  10Xcc
456  call assert_equal(6, g:Xgetlist({'idx':0}).idx)
457  Xlast
458  Xprev
459  call assert_equal('Xqftestfile2', bufname('%'))
460  call assert_equal(11, line('.'))
461  call assert_fails('Xnext', 'E553')
462  call assert_fails('Xnfile', 'E553')
463  Xrewind
464  call assert_equal('Xqftestfile1', bufname('%'))
465  call assert_equal(5, line('.'))
466
467  10Xnext
468  call assert_equal('Xqftestfile2', bufname('%'))
469  call assert_equal(11, line('.'))
470  10Xprev
471  call assert_equal('Xqftestfile1', bufname('%'))
472  call assert_equal(5, line('.'))
473
474  " Jumping to an error from the error window using cc command
475  Xgetexpr ['Xqftestfile1:5:Line5',
476		\ 'Xqftestfile1:6:Line6',
477		\ 'Xqftestfile2:10:Line10',
478		\ 'Xqftestfile2:11:Line11']
479  Xopen
480  10Xcc
481  call assert_equal(11, line('.'))
482  call assert_equal('Xqftestfile2', bufname('%'))
483
484  " Jumping to an error from the error window (when only the error window is
485  " present)
486  Xopen | only
487  Xlast 1
488  call assert_equal(5, line('.'))
489  call assert_equal('Xqftestfile1', bufname('%'))
490
491  Xexpr ""
492  call assert_fails('Xnext', 'E42:')
493
494  call delete('Xqftestfile1')
495  call delete('Xqftestfile2')
496
497  " Should be able to use next/prev with invalid entries
498  Xexpr ""
499  call assert_equal(0, g:Xgetlist({'idx' : 0}).idx)
500  call assert_equal(0, g:Xgetlist({'size' : 0}).size)
501  Xaddexpr ['foo', 'bar', 'baz', 'quux', 'shmoo']
502  call assert_equal(5, g:Xgetlist({'size' : 0}).size)
503  Xlast
504  call assert_equal(5, g:Xgetlist({'idx' : 0}).idx)
505  Xfirst
506  call assert_equal(1, g:Xgetlist({'idx' : 0}).idx)
507  2Xnext
508  call assert_equal(3, g:Xgetlist({'idx' : 0}).idx)
509endfunc
510
511func Test_browse()
512  call Xtest_browse('c')
513  call Xtest_browse('l')
514endfunc
515
516func Test_nomem()
517  call test_alloc_fail(GetAllocId('qf_dirname_start'), 0, 0)
518  call assert_fails('vimgrep vim runtest.vim', 'E342:')
519
520  call test_alloc_fail(GetAllocId('qf_dirname_now'), 0, 0)
521  call assert_fails('vimgrep vim runtest.vim', 'E342:')
522
523  call test_alloc_fail(GetAllocId('qf_namebuf'), 0, 0)
524  call assert_fails('cfile runtest.vim', 'E342:')
525
526  call test_alloc_fail(GetAllocId('qf_errmsg'), 0, 0)
527  call assert_fails('cfile runtest.vim', 'E342:')
528
529  call test_alloc_fail(GetAllocId('qf_pattern'), 0, 0)
530  call assert_fails('cfile runtest.vim', 'E342:')
531
532endfunc
533
534func s:test_xhelpgrep(cchar)
535  call s:setup_commands(a:cchar)
536  Xhelpgrep quickfix
537  Xopen
538  if a:cchar == 'c'
539    let title_text = ':helpgrep quickfix'
540  else
541    let title_text = ':lhelpgrep quickfix'
542  endif
543  call assert_true(w:quickfix_title =~ title_text, w:quickfix_title)
544
545  " Jumping to a help topic should open the help window
546  only
547  Xnext
548  call assert_true(&buftype == 'help')
549  call assert_true(winnr('$') == 2)
550  " Jumping to the next match should reuse the help window
551  Xnext
552  call assert_true(&buftype == 'help')
553  call assert_true(winnr() == 1)
554  call assert_true(winnr('$') == 2)
555  " Jumping to the next match from the quickfix window should reuse the help
556  " window
557  Xopen
558  Xnext
559  call assert_true(&buftype == 'help')
560  call assert_true(winnr() == 1)
561  call assert_true(winnr('$') == 2)
562
563  " This wipes out the buffer, make sure that doesn't cause trouble.
564  Xclose
565
566  if a:cchar == 'l'
567      " When a help window is present, running :lhelpgrep should reuse the
568      " help window and not the current window
569      new | only
570      call g:Xsetlist([], 'f')
571      help index.txt
572      wincmd w
573      lhelpgrep quickfix
574      call assert_equal(1, winnr())
575      call assert_notequal([], getloclist(1))
576      call assert_equal([], getloclist(2))
577  endif
578
579  new | only
580
581  " Search for non existing help string
582  call assert_fails('Xhelpgrep a1b2c3', 'E480:')
583  " Invalid regular expression
584  call assert_fails('Xhelpgrep \@<!', 'E480:')
585endfunc
586
587func Test_helpgrep()
588  call s:test_xhelpgrep('c')
589  helpclose
590  call s:test_xhelpgrep('l')
591endfunc
592
593func Test_errortitle()
594  augroup QfBufWinEnter
595    au!
596    au BufWinEnter * :let g:a=get(w:, 'quickfix_title', 'NONE')
597  augroup END
598  copen
599  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'')'}]
600  call setqflist(a)
601  call assert_equal(':setqflist()', g:a)
602  augroup QfBufWinEnter
603    au!
604  augroup END
605  augroup! QfBufWinEnter
606endfunc
607
608func Test_vimgreptitle()
609  augroup QfBufWinEnter
610    au!
611    au BufWinEnter * :let g:a=get(w:, 'quickfix_title', 'NONE')
612  augroup END
613  try
614    vimgrep /pattern/j file
615  catch /E480/
616  endtry
617  copen
618  call assert_equal(':    vimgrep /pattern/j file', g:a)
619  augroup QfBufWinEnter
620    au!
621  augroup END
622  augroup! QfBufWinEnter
623endfunc
624
625func XqfTitleTests(cchar)
626  call s:setup_commands(a:cchar)
627
628  Xgetexpr ['file:1:1:message']
629  let l = g:Xgetlist()
630  if a:cchar == 'c'
631    call setqflist(l, 'r')
632  else
633    call setloclist(0, l, 'r')
634  endif
635
636  Xopen
637  if a:cchar == 'c'
638    let title = ':setqflist()'
639  else
640    let title = ':setloclist()'
641  endif
642  call assert_equal(title, w:quickfix_title)
643  Xclose
644endfunc
645
646" Tests for quickfix window's title
647func Test_qf_title()
648  call XqfTitleTests('c')
649  call XqfTitleTests('l')
650endfunc
651
652" Tests for 'errorformat'
653func Test_efm()
654  let save_efm = &efm
655  set efm=%EEEE%m,%WWWW%m,%+CCCC%.%#,%-GGGG%.%#
656  cgetexpr ['WWWW', 'EEEE', 'CCCC']
657  let l = strtrans(string(map(getqflist(), '[v:val.text, v:val.valid]')))
658  call assert_equal("[['W', 1], ['E^@CCCC', 1]]", l)
659  cgetexpr ['WWWW', 'GGGG', 'EEEE', 'CCCC']
660  let l = strtrans(string(map(getqflist(), '[v:val.text, v:val.valid]')))
661  call assert_equal("[['W', 1], ['E^@CCCC', 1]]", l)
662  cgetexpr ['WWWW', 'GGGG', 'ZZZZ', 'EEEE', 'CCCC', 'YYYY']
663  let l = strtrans(string(map(getqflist(), '[v:val.text, v:val.valid]')))
664  call assert_equal("[['W', 1], ['ZZZZ', 0], ['E^@CCCC', 1], ['YYYY', 0]]", l)
665  let &efm = save_efm
666endfunc
667
668" This will test for problems in quickfix:
669" A. incorrectly copying location lists which caused the location list to show
670"    a different name than the file that was actually being displayed.
671" B. not reusing the window for which the location list window is opened but
672"    instead creating new windows.
673" C. make sure that the location list window is not reused instead of the
674"    window it belongs to.
675"
676" Set up the test environment:
677func ReadTestProtocol(name)
678  let base = substitute(a:name, '\v^test://(.*)%(\.[^.]+)?', '\1', '')
679  let word = substitute(base, '\v(.*)\..*', '\1', '')
680
681  setl modifiable
682  setl noreadonly
683  setl noswapfile
684  setl bufhidden=delete
685  %del _
686  " For problem 2:
687  " 'buftype' has to be set to reproduce the constant opening of new windows
688  setl buftype=nofile
689
690  call setline(1, word)
691
692  setl nomodified
693  setl nomodifiable
694  setl readonly
695  exe 'doautocmd BufRead ' . substitute(a:name, '\v^test://(.*)', '\1', '')
696endfunc
697
698func Test_locationlist()
699    enew
700
701    augroup testgroup
702      au!
703      autocmd BufReadCmd test://* call ReadTestProtocol(expand("<amatch>"))
704    augroup END
705
706    let words = [ "foo", "bar", "baz", "quux", "shmoo", "spam", "eggs" ]
707
708    let qflist = []
709    for word in words
710      call add(qflist, {'filename': 'test://' . word . '.txt', 'text': 'file ' . word . '.txt', })
711      " NOTE: problem 1:
712      " intentionally not setting 'lnum' so that the quickfix entries are not
713      " valid
714      call setloclist(0, qflist, ' ')
715    endfor
716
717    " Test A
718    lrewind
719    enew
720    lopen
721    4lnext
722    vert split
723    wincmd L
724    lopen
725    wincmd p
726    lnext
727    let fileName = expand("%")
728    wincmd p
729    let locationListFileName = substitute(getline(line('.')), '\([^|]*\)|.*', '\1', '')
730    let fileName = substitute(fileName, '\\', '/', 'g')
731    let locationListFileName = substitute(locationListFileName, '\\', '/', 'g')
732    call assert_equal("test://bar.txt", fileName)
733    call assert_equal("test://bar.txt", locationListFileName)
734
735    wincmd n | only
736
737    " Test B:
738    lrewind
739    lopen
740    2
741    exe "normal \<CR>"
742    wincmd p
743    3
744    exe "normal \<CR>"
745    wincmd p
746    4
747    exe "normal \<CR>"
748    call assert_equal(2, winnr('$'))
749    wincmd n | only
750
751    " Test C:
752    lrewind
753    lopen
754    " Let's move the location list window to the top to check whether it (the
755    " first window found) will be reused when we try to open new windows:
756    wincmd K
757    2
758    exe "normal \<CR>"
759    wincmd p
760    3
761    exe "normal \<CR>"
762    wincmd p
763    4
764    exe "normal \<CR>"
765    1wincmd w
766    call assert_equal('quickfix', &buftype)
767    2wincmd w
768    let bufferName = expand("%")
769    let bufferName = substitute(bufferName, '\\', '/', 'g')
770    call assert_equal('test://quux.txt', bufferName)
771
772    wincmd n | only
773
774    augroup! testgroup
775endfunc
776
777func Test_locationlist_curwin_was_closed()
778    augroup testgroup
779      au!
780      autocmd BufReadCmd test_curwin.txt call R(expand("<amatch>"))
781    augroup END
782
783    func! R(n)
784      quit
785    endfunc
786
787    new
788    let q = []
789    call add(q, {'filename': 'test_curwin.txt' })
790    call setloclist(0, q)
791    call assert_fails('lrewind', 'E924:')
792
793    augroup! testgroup
794endfunc
795
796func Test_locationlist_cross_tab_jump()
797  call writefile(['loclistfoo'], 'loclistfoo')
798  call writefile(['loclistbar'], 'loclistbar')
799  set switchbuf=usetab
800
801  edit loclistfoo
802  tabedit loclistbar
803  silent lgrep loclistfoo loclist*
804  call assert_equal(1, tabpagenr())
805
806  enew | only | tabonly
807  set switchbuf&vim
808  call delete('loclistfoo')
809  call delete('loclistbar')
810endfunc
811
812" More tests for 'errorformat'
813func Test_efm1()
814    if !has('unix')
815	" The 'errorformat' setting is different on non-Unix systems.
816	" This test works only on Unix-like systems.
817	return
818    endif
819
820    let l =<< trim [DATA]
821      "Xtestfile", line 4.12: 1506-045 (S) Undeclared identifier fd_set.
822      "Xtestfile", line 6 col 19; this is an error
823      gcc -c -DHAVE_CONFIsing-prototypes -I/usr/X11R6/include  version.c
824      Xtestfile:9: parse error before `asd'
825      make: *** [vim] Error 1
826      in file "Xtestfile" linenr 10: there is an error
827
828      2 returned
829      "Xtestfile", line 11 col 1; this is an error
830      "Xtestfile", line 12 col 2; this is another error
831      "Xtestfile", line 14:10; this is an error in column 10
832      =Xtestfile=, line 15:10; this is another error, but in vcol 10 this time
833      "Xtestfile", linenr 16: yet another problem
834      Error in "Xtestfile" at line 17:
835      x should be a dot
836      	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 17
837                  ^
838      Error in "Xtestfile" at line 18:
839      x should be a dot
840      	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 18
841      .............^
842      Error in "Xtestfile" at line 19:
843      x should be a dot
844      	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 19
845      --------------^
846      Error in "Xtestfile" at line 20:
847      x should be a dot
848      	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 20
849      	       ^
850
851      Does anyone know what is the problem and how to correction it?
852      "Xtestfile", line 21 col 9: What is the title of the quickfix window?
853      "Xtestfile", line 22 col 9: What is the title of the quickfix window?
854    [DATA]
855
856    call writefile(l, 'Xerrorfile1')
857    call writefile(l[:-2], 'Xerrorfile2')
858
859    let m =<< [DATA]
860	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  2
861	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  3
862	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  4
863	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  5
864	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  6
865	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  7
866	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  8
867	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  9
868	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 10
869	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 11
870	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 12
871	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 13
872	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 14
873	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 15
874	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 16
875	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 17
876	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 18
877	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 19
878	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 20
879	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 21
880	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 22
881[DATA]
882    call writefile(m, 'Xtestfile')
883
884    let save_efm = &efm
885    set efm+==%f=\\,\ line\ %l%*\\D%v%*[^\ ]\ %m
886    set efm^=%AError\ in\ \"%f\"\ at\ line\ %l:,%Z%p^,%C%m
887
888    exe 'cf Xerrorfile2'
889    clast
890    copen
891    call assert_equal(':cf Xerrorfile2', w:quickfix_title)
892    wincmd p
893
894    exe 'cf Xerrorfile1'
895    call assert_equal([4, 12], [line('.'), col('.')])
896    cn
897    call assert_equal([6, 19], [line('.'), col('.')])
898    cn
899    call assert_equal([9, 2], [line('.'), col('.')])
900    cn
901    call assert_equal([10, 2], [line('.'), col('.')])
902    cn
903    call assert_equal([11, 1], [line('.'), col('.')])
904    cn
905    call assert_equal([12, 2], [line('.'), col('.')])
906    cn
907    call assert_equal([14, 10], [line('.'), col('.')])
908    cn
909    call assert_equal([15, 3, 10], [line('.'), col('.'), virtcol('.')])
910    cn
911    call assert_equal([16, 2], [line('.'), col('.')])
912    cn
913    call assert_equal([17, 6], [line('.'), col('.')])
914    cn
915    call assert_equal([18, 7], [line('.'), col('.')])
916    cn
917    call assert_equal([19, 8], [line('.'), col('.')])
918    cn
919    call assert_equal([20, 9], [line('.'), col('.')])
920    clast
921    cprev
922    cprev
923    wincmd w
924    call assert_equal(':cf Xerrorfile1', w:quickfix_title)
925    wincmd p
926
927    let &efm = save_efm
928    call delete('Xerrorfile1')
929    call delete('Xerrorfile2')
930    call delete('Xtestfile')
931endfunc
932
933" Test for quickfix directory stack support
934func s:dir_stack_tests(cchar)
935  call s:setup_commands(a:cchar)
936
937  let save_efm=&efm
938  set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f'
939
940  let lines = ["Entering dir 'dir1/a'",
941		\ 'habits2.txt:1:Nine Healthy Habits',
942		\ "Entering dir 'b'",
943		\ 'habits3.txt:2:0 Hours of television',
944		\ 'habits2.txt:7:5 Small meals',
945		\ "Entering dir 'dir1/c'",
946		\ 'habits4.txt:3:1 Hour of exercise',
947		\ "Leaving dir 'dir1/c'",
948		\ "Leaving dir 'dir1/a'",
949		\ 'habits1.txt:4:2 Liters of water',
950		\ "Entering dir 'dir2'",
951		\ 'habits5.txt:5:3 Cups of hot green tea',
952		\ "Leaving dir 'dir2'"
953		\]
954
955  Xexpr ""
956  for l in lines
957      Xaddexpr l
958  endfor
959
960  let qf = g:Xgetlist()
961
962  call assert_equal('dir1/a/habits2.txt', bufname(qf[1].bufnr))
963  call assert_equal(1, qf[1].lnum)
964  call assert_equal('dir1/a/b/habits3.txt', bufname(qf[3].bufnr))
965  call assert_equal(2, qf[3].lnum)
966  call assert_equal('dir1/a/habits2.txt', bufname(qf[4].bufnr))
967  call assert_equal(7, qf[4].lnum)
968  call assert_equal('dir1/c/habits4.txt', bufname(qf[6].bufnr))
969  call assert_equal(3, qf[6].lnum)
970  call assert_equal('habits1.txt', bufname(qf[9].bufnr))
971  call assert_equal(4, qf[9].lnum)
972  call assert_equal('dir2/habits5.txt', bufname(qf[11].bufnr))
973  call assert_equal(5, qf[11].lnum)
974
975  let &efm=save_efm
976endfunc
977
978" Tests for %D and %X errorformat options
979func Test_efm_dirstack()
980  " Create the directory stack and files
981  call mkdir('dir1')
982  call mkdir('dir1/a')
983  call mkdir('dir1/a/b')
984  call mkdir('dir1/c')
985  call mkdir('dir2')
986
987  let lines = ["Nine Healthy Habits",
988		\ "0 Hours of television",
989		\ "1 Hour of exercise",
990		\ "2 Liters of water",
991		\ "3 Cups of hot green tea",
992		\ "4 Short mental breaks",
993		\ "5 Small meals",
994		\ "6 AM wake up time",
995		\ "7 Minutes of laughter",
996		\ "8 Hours of sleep (at least)",
997		\ "9 PM end of the day and off to bed"
998		\ ]
999  call writefile(lines, 'habits1.txt')
1000  call writefile(lines, 'dir1/a/habits2.txt')
1001  call writefile(lines, 'dir1/a/b/habits3.txt')
1002  call writefile(lines, 'dir1/c/habits4.txt')
1003  call writefile(lines, 'dir2/habits5.txt')
1004
1005  call s:dir_stack_tests('c')
1006  call s:dir_stack_tests('l')
1007
1008  call delete('dir1', 'rf')
1009  call delete('dir2', 'rf')
1010  call delete('habits1.txt')
1011endfunc
1012
1013" Test for resync after continuing an ignored message
1014func Xefm_ignore_continuations(cchar)
1015  call s:setup_commands(a:cchar)
1016
1017  let save_efm = &efm
1018
1019  let &efm =
1020	\ '%Eerror %m %l,' .
1021	\ '%-Wignored %m %l,' .
1022	\ '%+Cmore ignored %m %l,' .
1023	\ '%Zignored end'
1024  Xgetexpr ['ignored warning 1', 'more ignored continuation 2', 'ignored end', 'error resync 4']
1025  let l = map(g:Xgetlist(), '[v:val.text, v:val.valid, v:val.lnum, v:val.type]')
1026  call assert_equal([['resync', 1, 4, 'E']], l)
1027
1028  let &efm = save_efm
1029endfunc
1030
1031func Test_efm_ignore_continuations()
1032  call Xefm_ignore_continuations('c')
1033  call Xefm_ignore_continuations('l')
1034endfunc
1035
1036" Tests for invalid error format specifies
1037func Xinvalid_efm_Tests(cchar)
1038  call s:setup_commands(a:cchar)
1039
1040  let save_efm = &efm
1041
1042  set efm=%f:%l:%m,%f:%f:%l:%m
1043  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E372:')
1044
1045  set efm=%f:%l:%m,%f:%l:%r:%m
1046  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E373:')
1047
1048  set efm=%f:%l:%m,%O:%f:%l:%m
1049  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E373:')
1050
1051  set efm=%f:%l:%m,%f:%l:%*[^a-z
1052  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E374:')
1053
1054  set efm=%f:%l:%m,%f:%l:%*c
1055  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E375:')
1056
1057  set efm=%f:%l:%m,%L%M%N
1058  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E376:')
1059
1060  set efm=%f:%l:%m,%f:%l:%m:%R
1061  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E377:')
1062
1063  set efm=
1064  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E378:')
1065
1066  set efm=%DEntering\ dir\ abc,%f:%l:%m
1067  call assert_fails('Xexpr ["Entering dir abc", "abc.txt:1:Hello world"]', 'E379:')
1068
1069  let &efm = save_efm
1070endfunc
1071
1072func Test_invalid_efm()
1073  call Xinvalid_efm_Tests('c')
1074  call Xinvalid_efm_Tests('l')
1075endfunc
1076
1077" TODO:
1078" Add tests for the following formats in 'errorformat'
1079"	%r  %O
1080func Test_efm2()
1081  let save_efm = &efm
1082
1083  " Test for %s format in efm
1084  set efm=%f:%s
1085  cexpr 'Xtestfile:Line search text'
1086  let l = getqflist()
1087  call assert_equal(l[0].pattern, '^\VLine search text\$')
1088  call assert_equal(l[0].lnum, 0)
1089
1090  let l = split(execute('clist', ''), "\n")
1091  call assert_equal([' 1 Xtestfile:^\VLine search text\$:  '], l)
1092
1093  " Test for %P, %Q and %t format specifiers
1094  let lines =<< trim [DATA]
1095    [Xtestfile1]
1096    (1,17)  error: ';' missing
1097    (21,2)  warning: variable 'z' not defined
1098    (67,3)  error: end of file found before string ended
1099    --
1100
1101    [Xtestfile2]
1102    --
1103
1104    [Xtestfile3]
1105    NEW compiler v1.1
1106    (2,2)   warning: variable 'x' not defined
1107    (67,3)  warning: 's' already defined
1108    --
1109  [DATA]
1110
1111  set efm=%+P[%f]%r,(%l\\,%c)%*[\ ]%t%*[^:]:\ %m,%+Q--%r
1112  " To exercise the push/pop file functionality in quickfix, the test files
1113  " need to be created.
1114  call writefile(['Line1'], 'Xtestfile1')
1115  call writefile(['Line2'], 'Xtestfile2')
1116  call writefile(['Line3'], 'Xtestfile3')
1117  cexpr ""
1118  for l in lines
1119      caddexpr l
1120  endfor
1121  let l = getqflist()
1122  call assert_equal(12, len(l))
1123  call assert_equal(21, l[2].lnum)
1124  call assert_equal(2, l[2].col)
1125  call assert_equal('w', l[2].type)
1126  call assert_equal('e', l[3].type)
1127  call delete('Xtestfile1')
1128  call delete('Xtestfile2')
1129  call delete('Xtestfile3')
1130
1131  " Tests for %E, %C and %Z format specifiers
1132  let lines =<< trim [DATA]
1133    Error 275
1134    line 42
1135    column 3
1136    ' ' expected after '--'
1137  [DATA]
1138
1139  set efm=%EError\ %n,%Cline\ %l,%Ccolumn\ %c,%Z%m
1140  cgetexpr lines
1141  let l = getqflist()
1142  call assert_equal(275, l[0].nr)
1143  call assert_equal(42, l[0].lnum)
1144  call assert_equal(3, l[0].col)
1145  call assert_equal('E', l[0].type)
1146  call assert_equal("\n' ' expected after '--'", l[0].text)
1147
1148  " Test for %>
1149  let lines =<< trim [DATA]
1150    Error in line 147 of foo.c:
1151    unknown variable 'i'
1152  [DATA]
1153
1154  set efm=unknown\ variable\ %m,%E%>Error\ in\ line\ %l\ of\ %f:,%Z%m
1155  cgetexpr lines
1156  let l = getqflist()
1157  call assert_equal(147, l[0].lnum)
1158  call assert_equal('E', l[0].type)
1159  call assert_equal("\nunknown variable 'i'", l[0].text)
1160
1161  " Test for %A, %C and other formats
1162  let lines =<< trim [DATA]
1163    ==============================================================
1164    FAIL: testGetTypeIdCachesResult (dbfacadeTest.DjsDBFacadeTest)
1165    --------------------------------------------------------------
1166    Traceback (most recent call last):
1167      File "unittests/dbfacadeTest.py", line 89, in testFoo
1168        self.assertEquals(34, dtid)
1169      File "/usr/lib/python2.2/unittest.py", line 286, in
1170     failUnlessEqual
1171        raise self.failureException, \\
1172    AssertionError: 34 != 33
1173
1174    --------------------------------------------------------------
1175    Ran 27 tests in 0.063s
1176  [DATA]
1177
1178  set efm=%C\ %.%#,%A\ \ File\ \"%f\"\\,\ line\ %l%.%#,%Z%[%^\ ]%\\@=%m
1179  cgetexpr lines
1180  let l = getqflist()
1181  call assert_equal(8, len(l))
1182  call assert_equal(89, l[4].lnum)
1183  call assert_equal(1, l[4].valid)
1184  call assert_equal('unittests/dbfacadeTest.py', bufname(l[4].bufnr))
1185
1186  " Test for %o
1187  set efm=%f(%o):%l\ %m
1188  cgetexpr ['Xotestfile(Language.PureScript.Types):20 Error']
1189  call writefile(['Line1'], 'Xotestfile')
1190  let l = getqflist()
1191  call assert_equal(1, len(l), string(l))
1192  call assert_equal('Language.PureScript.Types', l[0].module)
1193  copen
1194  call assert_equal('Language.PureScript.Types|20| Error', getline(1))
1195  call feedkeys("\<CR>", 'xn')
1196  call assert_equal('Xotestfile', expand('%:t'))
1197  cclose
1198  bd
1199  call delete("Xotestfile")
1200
1201  " The following sequence of commands used to crash Vim
1202  set efm=%W%m
1203  cgetexpr ['msg1']
1204  let l = getqflist()
1205  call assert_equal(1, len(l), string(l))
1206  call assert_equal('msg1', l[0].text)
1207  set efm=%C%m
1208  lexpr 'msg2'
1209  let l = getloclist(0)
1210  call assert_equal(1, len(l), string(l))
1211  call assert_equal('msg2', l[0].text)
1212  lopen
1213  call setqflist([], 'r')
1214  caddbuf
1215  let l = getqflist()
1216  call assert_equal(1, len(l), string(l))
1217  call assert_equal('|| msg2', l[0].text)
1218
1219  " When matching error lines, case should be ignored. Test for this.
1220  set noignorecase
1221  let l=getqflist({'lines' : ['Xtest:FOO10:Line 20'], 'efm':'%f:foo%l:%m'})
1222  call assert_equal(10, l.items[0].lnum)
1223  call assert_equal('Line 20', l.items[0].text)
1224  set ignorecase&
1225
1226  new | only
1227  let &efm = save_efm
1228endfunc
1229
1230func XquickfixChangedByAutocmd(cchar)
1231  call s:setup_commands(a:cchar)
1232  if a:cchar == 'c'
1233    let ErrorNr = 'E925'
1234    func! ReadFunc()
1235      colder
1236      cgetexpr []
1237    endfunc
1238  else
1239    let ErrorNr = 'E926'
1240    func! ReadFunc()
1241      lolder
1242      lgetexpr []
1243    endfunc
1244  endif
1245
1246  augroup testgroup
1247    au!
1248    autocmd BufReadCmd test_changed.txt call ReadFunc()
1249  augroup END
1250
1251  new | only
1252  let words = [ "a", "b" ]
1253  let qflist = []
1254  for word in words
1255    call add(qflist, {'filename': 'test_changed.txt'})
1256    call g:Xsetlist(qflist, ' ')
1257  endfor
1258  call assert_fails('Xrewind', ErrorNr . ':')
1259
1260  augroup! testgroup
1261endfunc
1262
1263func Test_quickfix_was_changed_by_autocmd()
1264  call XquickfixChangedByAutocmd('c')
1265  call XquickfixChangedByAutocmd('l')
1266endfunc
1267
1268func Test_caddbuffer_to_empty()
1269  helpgr quickfix
1270  call setqflist([], 'r')
1271  cad
1272  try
1273    cn
1274  catch
1275    " number of matches is unknown
1276    call assert_true(v:exception =~ 'E553:')
1277  endtry
1278  quit!
1279endfunc
1280
1281func Test_cgetexpr_works()
1282  " this must not crash Vim
1283  cgetexpr [$x]
1284  lgetexpr [$x]
1285endfunc
1286
1287" Tests for the setqflist() and setloclist() functions
1288func SetXlistTests(cchar, bnum)
1289  call s:setup_commands(a:cchar)
1290
1291  call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 1},
1292	      \  {'bufnr': a:bnum, 'lnum': 2}])
1293  let l = g:Xgetlist()
1294  call assert_equal(2, len(l))
1295  call assert_equal(2, l[1].lnum)
1296
1297  Xnext
1298  call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 3}], 'a')
1299  let l = g:Xgetlist()
1300  call assert_equal(3, len(l))
1301  Xnext
1302  call assert_equal(3, line('.'))
1303
1304  " Appending entries to the list should not change the cursor position
1305  " in the quickfix window
1306  Xwindow
1307  1
1308  call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 4},
1309	      \  {'bufnr': a:bnum, 'lnum': 5}], 'a')
1310  call assert_equal(1, line('.'))
1311  close
1312
1313  call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 3},
1314	      \  {'bufnr': a:bnum, 'lnum': 4},
1315	      \  {'bufnr': a:bnum, 'lnum': 5}], 'r')
1316  let l = g:Xgetlist()
1317  call assert_equal(3, len(l))
1318  call assert_equal(5, l[2].lnum)
1319
1320  call g:Xsetlist([])
1321  let l = g:Xgetlist()
1322  call assert_equal(0, len(l))
1323
1324  " Tests for setting the 'valid' flag
1325  call g:Xsetlist([{'bufnr':a:bnum, 'lnum':4, 'valid':0}])
1326  Xwindow
1327  call assert_equal(1, winnr('$'))
1328  let l = g:Xgetlist()
1329  call g:Xsetlist(l)
1330  call assert_equal(0, g:Xgetlist()[0].valid)
1331  " Adding a non-valid entry should not mark the list as having valid entries
1332  call g:Xsetlist([{'bufnr':a:bnum, 'lnum':5, 'valid':0}], 'a')
1333  Xwindow
1334  call assert_equal(1, winnr('$'))
1335
1336  " :cnext/:cprev should still work even with invalid entries in the list
1337  let l = [{'bufnr' : a:bnum, 'lnum' : 1, 'text' : '1', 'valid' : 0},
1338	      \ {'bufnr' : a:bnum, 'lnum' : 2, 'text' : '2', 'valid' : 0}]
1339  call g:Xsetlist(l)
1340  Xnext
1341  call assert_equal(2, g:Xgetlist({'idx' : 0}).idx)
1342  Xprev
1343  call assert_equal(1, g:Xgetlist({'idx' : 0}).idx)
1344  " :cnext/:cprev should still work after appending invalid entries to an
1345  " empty list
1346  call g:Xsetlist([])
1347  call g:Xsetlist(l, 'a')
1348  Xnext
1349  call assert_equal(2, g:Xgetlist({'idx' : 0}).idx)
1350  Xprev
1351  call assert_equal(1, g:Xgetlist({'idx' : 0}).idx)
1352
1353  call g:Xsetlist([{'text':'Text1', 'valid':1}])
1354  Xwindow
1355  call assert_equal(2, winnr('$'))
1356  Xclose
1357  let save_efm = &efm
1358  set efm=%m
1359  Xgetexpr 'TestMessage'
1360  let l = g:Xgetlist()
1361  call g:Xsetlist(l)
1362  call assert_equal(1, g:Xgetlist()[0].valid)
1363  let &efm = save_efm
1364
1365  " Error cases:
1366  " Refer to a non-existing buffer and pass a non-dictionary type
1367  call assert_fails("call g:Xsetlist([{'bufnr':998, 'lnum':4}," .
1368	      \ " {'bufnr':999, 'lnum':5}])", 'E92:')
1369  call g:Xsetlist([[1, 2,3]])
1370  call assert_equal(0, len(g:Xgetlist()))
1371endfunc
1372
1373func Test_setqflist()
1374  new Xtestfile | only
1375  let bnum = bufnr('%')
1376  call setline(1, range(1,5))
1377
1378  call SetXlistTests('c', bnum)
1379  call SetXlistTests('l', bnum)
1380
1381  enew!
1382  call delete('Xtestfile')
1383endfunc
1384
1385func Xlist_empty_middle(cchar)
1386  call s:setup_commands(a:cchar)
1387
1388  " create three quickfix lists
1389  let @/ = 'Test_'
1390  Xvimgrep // test_quickfix.vim
1391  let testlen = len(g:Xgetlist())
1392  call assert_true(testlen > 0)
1393  Xvimgrep empty test_quickfix.vim
1394  call assert_true(len(g:Xgetlist()) > 0)
1395  Xvimgrep matches test_quickfix.vim
1396  let matchlen = len(g:Xgetlist())
1397  call assert_true(matchlen > 0)
1398  Xolder
1399  " make the middle list empty
1400  call g:Xsetlist([], 'r')
1401  call assert_true(len(g:Xgetlist()) == 0)
1402  Xolder
1403  call assert_equal(testlen, len(g:Xgetlist()))
1404  Xnewer
1405  Xnewer
1406  call assert_equal(matchlen, len(g:Xgetlist()))
1407endfunc
1408
1409func Test_setqflist_empty_middle()
1410  call Xlist_empty_middle('c')
1411  call Xlist_empty_middle('l')
1412endfunc
1413
1414func Xlist_empty_older(cchar)
1415  call s:setup_commands(a:cchar)
1416
1417  " create three quickfix lists
1418  Xvimgrep one test_quickfix.vim
1419  let onelen = len(g:Xgetlist())
1420  call assert_true(onelen > 0)
1421  Xvimgrep two test_quickfix.vim
1422  let twolen = len(g:Xgetlist())
1423  call assert_true(twolen > 0)
1424  Xvimgrep three test_quickfix.vim
1425  let threelen = len(g:Xgetlist())
1426  call assert_true(threelen > 0)
1427  Xolder 2
1428  " make the first list empty, check the others didn't change
1429  call g:Xsetlist([], 'r')
1430  call assert_true(len(g:Xgetlist()) == 0)
1431  Xnewer
1432  call assert_equal(twolen, len(g:Xgetlist()))
1433  Xnewer
1434  call assert_equal(threelen, len(g:Xgetlist()))
1435endfunc
1436
1437func Test_setqflist_empty_older()
1438  call Xlist_empty_older('c')
1439  call Xlist_empty_older('l')
1440endfunc
1441
1442func XquickfixSetListWithAct(cchar)
1443  call s:setup_commands(a:cchar)
1444
1445  let list1 = [{'filename': 'fnameA', 'text': 'A'},
1446          \    {'filename': 'fnameB', 'text': 'B'}]
1447  let list2 = [{'filename': 'fnameC', 'text': 'C'},
1448          \    {'filename': 'fnameD', 'text': 'D'},
1449          \    {'filename': 'fnameE', 'text': 'E'}]
1450
1451  " {action} is unspecified.  Same as specifying ' '.
1452  new | only
1453  silent! Xnewer 99
1454  call g:Xsetlist(list1)
1455  call g:Xsetlist(list2)
1456  let li = g:Xgetlist()
1457  call assert_equal(3, len(li))
1458  call assert_equal('C', li[0]['text'])
1459  call assert_equal('D', li[1]['text'])
1460  call assert_equal('E', li[2]['text'])
1461  silent! Xolder
1462  let li = g:Xgetlist()
1463  call assert_equal(2, len(li))
1464  call assert_equal('A', li[0]['text'])
1465  call assert_equal('B', li[1]['text'])
1466
1467  " {action} is specified ' '.
1468  new | only
1469  silent! Xnewer 99
1470  call g:Xsetlist(list1)
1471  call g:Xsetlist(list2, ' ')
1472  let li = g:Xgetlist()
1473  call assert_equal(3, len(li))
1474  call assert_equal('C', li[0]['text'])
1475  call assert_equal('D', li[1]['text'])
1476  call assert_equal('E', li[2]['text'])
1477  silent! Xolder
1478  let li = g:Xgetlist()
1479  call assert_equal(2, len(li))
1480  call assert_equal('A', li[0]['text'])
1481  call assert_equal('B', li[1]['text'])
1482
1483  " {action} is specified 'a'.
1484  new | only
1485  silent! Xnewer 99
1486  call g:Xsetlist(list1)
1487  call g:Xsetlist(list2, 'a')
1488  let li = g:Xgetlist()
1489  call assert_equal(5, len(li))
1490  call assert_equal('A', li[0]['text'])
1491  call assert_equal('B', li[1]['text'])
1492  call assert_equal('C', li[2]['text'])
1493  call assert_equal('D', li[3]['text'])
1494  call assert_equal('E', li[4]['text'])
1495
1496  " {action} is specified 'r'.
1497  new | only
1498  silent! Xnewer 99
1499  call g:Xsetlist(list1)
1500  call g:Xsetlist(list2, 'r')
1501  let li = g:Xgetlist()
1502  call assert_equal(3, len(li))
1503  call assert_equal('C', li[0]['text'])
1504  call assert_equal('D', li[1]['text'])
1505  call assert_equal('E', li[2]['text'])
1506
1507  " Test for wrong value.
1508  new | only
1509  call assert_fails("call g:Xsetlist(0)", 'E714:')
1510  call assert_fails("call g:Xsetlist(list1, '')", 'E927:')
1511  call assert_fails("call g:Xsetlist(list1, 'aa')", 'E927:')
1512  call assert_fails("call g:Xsetlist(list1, ' a')", 'E927:')
1513  call assert_fails("call g:Xsetlist(list1, 0)", 'E928:')
1514endfunc
1515
1516func Test_setqflist_invalid_nr()
1517  " The following command used to crash Vim
1518  call setqflist([], ' ', {'nr' : $XXX_DOES_NOT_EXIST})
1519endfunc
1520
1521func Test_quickfix_set_list_with_act()
1522  call XquickfixSetListWithAct('c')
1523  call XquickfixSetListWithAct('l')
1524endfunc
1525
1526func XLongLinesTests(cchar)
1527  let l = g:Xgetlist()
1528
1529  call assert_equal(4, len(l))
1530  call assert_equal(1, l[0].lnum)
1531  call assert_equal(1, l[0].col)
1532  call assert_equal(1975, len(l[0].text))
1533  call assert_equal(2, l[1].lnum)
1534  call assert_equal(1, l[1].col)
1535  call assert_equal(4070, len(l[1].text))
1536  call assert_equal(3, l[2].lnum)
1537  call assert_equal(1, l[2].col)
1538  call assert_equal(4070, len(l[2].text))
1539  call assert_equal(4, l[3].lnum)
1540  call assert_equal(1, l[3].col)
1541  call assert_equal(10, len(l[3].text))
1542
1543  call g:Xsetlist([], 'r')
1544endfunc
1545
1546func s:long_lines_tests(cchar)
1547  call s:setup_commands(a:cchar)
1548
1549  let testfile = 'samples/quickfix.txt'
1550
1551  " file
1552  exe 'Xgetfile' testfile
1553  call XLongLinesTests(a:cchar)
1554
1555  " list
1556  Xexpr readfile(testfile)
1557  call XLongLinesTests(a:cchar)
1558
1559  " string
1560  Xexpr join(readfile(testfile), "\n")
1561  call XLongLinesTests(a:cchar)
1562
1563  " buffer
1564  exe 'edit' testfile
1565  exe 'Xbuffer' bufnr('%')
1566  call XLongLinesTests(a:cchar)
1567endfunc
1568
1569func Test_long_lines()
1570  call s:long_lines_tests('c')
1571  call s:long_lines_tests('l')
1572endfunc
1573
1574func s:create_test_file(filename)
1575  let l = []
1576  for i in range(1, 20)
1577      call add(l, 'Line' . i)
1578  endfor
1579  call writefile(l, a:filename)
1580endfunc
1581
1582func Test_switchbuf()
1583  call s:create_test_file('Xqftestfile1')
1584  call s:create_test_file('Xqftestfile2')
1585  call s:create_test_file('Xqftestfile3')
1586
1587  new | only
1588  edit Xqftestfile1
1589  let file1_winid = win_getid()
1590  new Xqftestfile2
1591  let file2_winid = win_getid()
1592  cgetexpr ['Xqftestfile1:5:Line5',
1593		\ 'Xqftestfile1:6:Line6',
1594		\ 'Xqftestfile2:10:Line10',
1595		\ 'Xqftestfile2:11:Line11',
1596		\ 'Xqftestfile3:15:Line15',
1597		\ 'Xqftestfile3:16:Line16']
1598
1599  new
1600  let winid = win_getid()
1601  cfirst | cnext
1602  call assert_equal(winid, win_getid())
1603  2cnext
1604  call assert_equal(winid, win_getid())
1605  2cnext
1606  call assert_equal(winid, win_getid())
1607  enew
1608
1609  set switchbuf=useopen
1610  cfirst | cnext
1611  call assert_equal(file1_winid, win_getid())
1612  2cnext
1613  call assert_equal(file2_winid, win_getid())
1614  2cnext
1615  call assert_equal(file2_winid, win_getid())
1616
1617  enew | only
1618  set switchbuf=usetab
1619  tabedit Xqftestfile1
1620  tabedit Xqftestfile2
1621  tabedit Xqftestfile3
1622  tabfirst
1623  cfirst | cnext
1624  call assert_equal(2, tabpagenr())
1625  2cnext
1626  call assert_equal(3, tabpagenr())
1627  6cnext
1628  call assert_equal(4, tabpagenr())
1629  2cpfile
1630  call assert_equal(2, tabpagenr())
1631  2cnfile
1632  call assert_equal(4, tabpagenr())
1633  tabfirst | tabonly | enew
1634
1635  set switchbuf=split
1636  cfirst | cnext
1637  call assert_equal(1, winnr('$'))
1638  cnext | cnext
1639  call assert_equal(2, winnr('$'))
1640  cnext | cnext
1641  call assert_equal(3, winnr('$'))
1642  enew | only
1643
1644  set switchbuf=newtab
1645  cfirst | cnext
1646  call assert_equal(1, tabpagenr('$'))
1647  cnext | cnext
1648  call assert_equal(2, tabpagenr('$'))
1649  cnext | cnext
1650  call assert_equal(3, tabpagenr('$'))
1651  tabfirst | enew | tabonly | only
1652
1653  set switchbuf=
1654  edit Xqftestfile1
1655  let file1_winid = win_getid()
1656  new Xqftestfile2
1657  let file2_winid = win_getid()
1658  copen
1659  exe "normal 1G\<CR>"
1660  call assert_equal(file1_winid, win_getid())
1661  copen
1662  exe "normal 3G\<CR>"
1663  call assert_equal(file2_winid, win_getid())
1664  copen | only
1665  exe "normal 5G\<CR>"
1666  call assert_equal(2, winnr('$'))
1667  call assert_equal(1, bufwinnr('Xqftestfile3'))
1668
1669  " If only quickfix window is open in the current tabpage, jumping to an
1670  " entry with 'switchubf' set to 'usetab' should search in other tabpages.
1671  enew | only
1672  set switchbuf=usetab
1673  tabedit Xqftestfile1
1674  tabedit Xqftestfile2
1675  tabedit Xqftestfile3
1676  tabfirst
1677  copen | only
1678  clast
1679  call assert_equal(4, tabpagenr())
1680  tabfirst | tabonly | enew | only
1681
1682  call delete('Xqftestfile1')
1683  call delete('Xqftestfile2')
1684  call delete('Xqftestfile3')
1685  set switchbuf&vim
1686
1687  enew | only
1688endfunc
1689
1690func Xadjust_qflnum(cchar)
1691  call s:setup_commands(a:cchar)
1692
1693  enew | only
1694
1695  let fname = 'Xqftestfile' . a:cchar
1696  call s:create_test_file(fname)
1697  exe 'edit ' . fname
1698
1699  Xgetexpr [fname . ':5:Line5',
1700	      \ fname . ':10:Line10',
1701	      \ fname . ':15:Line15',
1702	      \ fname . ':20:Line20']
1703
1704  6,14delete
1705  call append(6, ['Buffer', 'Window'])
1706
1707  let l = g:Xgetlist()
1708
1709  call assert_equal(5, l[0].lnum)
1710  call assert_equal(6, l[2].lnum)
1711  call assert_equal(13, l[3].lnum)
1712
1713  enew!
1714  call delete(fname)
1715endfunc
1716
1717func Test_adjust_lnum()
1718  call setloclist(0, [])
1719  call Xadjust_qflnum('c')
1720  call setqflist([])
1721  call Xadjust_qflnum('l')
1722endfunc
1723
1724" Tests for the :grep/:lgrep and :grepadd/:lgrepadd commands
1725func s:test_xgrep(cchar)
1726  call s:setup_commands(a:cchar)
1727
1728  " The following lines are used for the grep test. Don't remove.
1729  " Grep_Test_Text: Match 1
1730  " Grep_Test_Text: Match 2
1731  " GrepAdd_Test_Text: Match 1
1732  " GrepAdd_Test_Text: Match 2
1733  enew! | only
1734  set makeef&vim
1735  silent Xgrep Grep_Test_Text: test_quickfix.vim
1736  call assert_true(len(g:Xgetlist()) == 3)
1737  Xopen
1738  call assert_true(w:quickfix_title =~ '^:grep')
1739  Xclose
1740  enew
1741  set makeef=Temp_File_##
1742  silent Xgrepadd GrepAdd_Test_Text: test_quickfix.vim
1743  call assert_true(len(g:Xgetlist()) == 6)
1744endfunc
1745
1746func Test_grep()
1747  if !has('unix')
1748    " The grepprg may not be set on non-Unix systems
1749    return
1750  endif
1751
1752  call s:test_xgrep('c')
1753  call s:test_xgrep('l')
1754endfunc
1755
1756func Test_two_windows()
1757  " Use one 'errorformat' for two windows.  Add an expression to each of them,
1758  " make sure they each keep their own state.
1759  set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f'
1760  call mkdir('Xone/a', 'p')
1761  call mkdir('Xtwo/a', 'p')
1762  let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7']
1763  call writefile(lines, 'Xone/a/one.txt')
1764  call writefile(lines, 'Xtwo/a/two.txt')
1765
1766  new one
1767  let one_id = win_getid()
1768  lexpr ""
1769  new two
1770  let two_id = win_getid()
1771  lexpr ""
1772
1773  laddexpr "Entering dir 'Xtwo/a'"
1774  call win_gotoid(one_id)
1775  laddexpr "Entering dir 'Xone/a'"
1776  call win_gotoid(two_id)
1777  laddexpr 'two.txt:5:two two two'
1778  call win_gotoid(one_id)
1779  laddexpr 'one.txt:3:one one one'
1780
1781  let loc_one = getloclist(one_id)
1782  call assert_equal('Xone/a/one.txt', bufname(loc_one[1].bufnr))
1783  call assert_equal(3, loc_one[1].lnum)
1784
1785  let loc_two = getloclist(two_id)
1786  call assert_equal('Xtwo/a/two.txt', bufname(loc_two[1].bufnr))
1787  call assert_equal(5, loc_two[1].lnum)
1788
1789  call win_gotoid(one_id)
1790  bwipe!
1791  call win_gotoid(two_id)
1792  bwipe!
1793  call delete('Xone', 'rf')
1794  call delete('Xtwo', 'rf')
1795endfunc
1796
1797func XbottomTests(cchar)
1798  call s:setup_commands(a:cchar)
1799
1800  " Calling lbottom without any errors should fail
1801  if a:cchar == 'l'
1802      call assert_fails('lbottom', 'E776:')
1803  endif
1804
1805  call g:Xsetlist([{'filename': 'foo', 'lnum': 42}])
1806  Xopen
1807  let wid = win_getid()
1808  call assert_equal(1, line('.'))
1809  wincmd w
1810  call g:Xsetlist([{'filename': 'var', 'lnum': 24}], 'a')
1811  Xbottom
1812  call win_gotoid(wid)
1813  call assert_equal(2, line('.'))
1814  Xclose
1815endfunc
1816
1817" Tests for the :cbottom and :lbottom commands
1818func Test_cbottom()
1819  call XbottomTests('c')
1820  call XbottomTests('l')
1821endfunc
1822
1823func HistoryTest(cchar)
1824  call s:setup_commands(a:cchar)
1825
1826  " clear all lists after the first one, then replace the first one.
1827  call g:Xsetlist([])
1828  call assert_fails('Xolder 99', 'E380:')
1829  let entry = {'filename': 'foo', 'lnum': 42}
1830  call g:Xsetlist([entry], 'r')
1831  call g:Xsetlist([entry, entry])
1832  call g:Xsetlist([entry, entry, entry])
1833  let res = split(execute(a:cchar . 'hist'), "\n")
1834  call assert_equal(3, len(res))
1835  let common = 'errors     :set' . (a:cchar == 'c' ? 'qf' : 'loc') . 'list()'
1836  call assert_equal('  error list 1 of 3; 1 ' . common, res[0])
1837  call assert_equal('  error list 2 of 3; 2 ' . common, res[1])
1838  call assert_equal('> error list 3 of 3; 3 ' . common, res[2])
1839
1840  " Test for changing the quickfix lists
1841  call assert_equal(3, g:Xgetlist({'nr' : 0}).nr)
1842  exe '1' . a:cchar . 'hist'
1843  call assert_equal(1, g:Xgetlist({'nr' : 0}).nr)
1844  exe '3' . a:cchar . 'hist'
1845  call assert_equal(3, g:Xgetlist({'nr' : 0}).nr)
1846  call assert_fails('-2' . a:cchar . 'hist', 'E16:')
1847  call assert_fails('4' . a:cchar . 'hist', 'E16:')
1848
1849  call g:Xsetlist([], 'f')
1850  let l = split(execute(a:cchar . 'hist'), "\n")
1851  call assert_equal('No entries', l[0])
1852  if a:cchar == 'c'
1853    call assert_fails('4chist', 'E16:')
1854  else
1855    call assert_fails('4lhist', 'E776:')
1856  endif
1857
1858  " An empty list should still show the stack history
1859  call g:Xsetlist([])
1860  let res = split(execute(a:cchar . 'hist'), "\n")
1861  call assert_equal('> error list 1 of 1; 0 ' . common, res[0])
1862
1863  call g:Xsetlist([], 'f')
1864endfunc
1865
1866func Test_history()
1867  call HistoryTest('c')
1868  call HistoryTest('l')
1869endfunc
1870
1871func Test_duplicate_buf()
1872  " make sure we can get the highest buffer number
1873  edit DoesNotExist
1874  edit DoesNotExist2
1875  let last_buffer = bufnr("$")
1876
1877  " make sure only one buffer is created
1878  call writefile(['this one', 'that one'], 'Xgrepthis')
1879  vimgrep one Xgrepthis
1880  vimgrep one Xgrepthis
1881  call assert_equal(last_buffer + 1, bufnr("$"))
1882
1883  call delete('Xgrepthis')
1884endfunc
1885
1886" Quickfix/Location list set/get properties tests
1887func Xproperty_tests(cchar)
1888    call s:setup_commands(a:cchar)
1889
1890    " Error cases
1891    call assert_fails('call g:Xgetlist(99)', 'E715:')
1892    call assert_fails('call g:Xsetlist(99)', 'E714:')
1893    call assert_fails('call g:Xsetlist([], "a", [])', 'E715:')
1894
1895    " Set and get the title
1896    call g:Xsetlist([])
1897    Xopen
1898    wincmd p
1899    call g:Xsetlist([{'filename':'foo', 'lnum':27}])
1900    let s = g:Xsetlist([], 'a', {'title' : 'Sample'})
1901    call assert_equal(0, s)
1902    let d = g:Xgetlist({"title":1})
1903    call assert_equal('Sample', d.title)
1904    " Try setting title to a non-string value
1905    call assert_equal(-1, g:Xsetlist([], 'a', {'title' : ['Test']}))
1906    call assert_equal('Sample', g:Xgetlist({"title":1}).title)
1907
1908    Xopen
1909    call assert_equal('Sample', w:quickfix_title)
1910    Xclose
1911
1912    " Tests for action argument
1913    silent! Xolder 999
1914    let qfnr = g:Xgetlist({'all':1}).nr
1915    call g:Xsetlist([], 'r', {'title' : 'N1'})
1916    call assert_equal('N1', g:Xgetlist({'all':1}).title)
1917    call g:Xsetlist([], ' ', {'title' : 'N2'})
1918    call assert_equal(qfnr + 1, g:Xgetlist({'all':1}).nr)
1919
1920    let res = g:Xgetlist({'nr': 0})
1921    call assert_equal(qfnr + 1, res.nr)
1922    call assert_equal(['nr'], keys(res))
1923
1924    call g:Xsetlist([], ' ', {'title' : 'N3'})
1925    call assert_equal('N2', g:Xgetlist({'nr':2, 'title':1}).title)
1926
1927    " Changing the title of an earlier quickfix list
1928    call g:Xsetlist([], 'r', {'title' : 'NewTitle', 'nr' : 2})
1929    call assert_equal('NewTitle', g:Xgetlist({'nr':2, 'title':1}).title)
1930
1931    " Changing the title of an invalid quickfix list
1932    call assert_equal(-1, g:Xsetlist([], ' ',
1933		\ {'title' : 'SomeTitle', 'nr' : 99}))
1934    call assert_equal(-1, g:Xsetlist([], ' ',
1935		\ {'title' : 'SomeTitle', 'nr' : 'abc'}))
1936
1937    if a:cchar == 'c'
1938	copen
1939	call assert_equal({'winid':win_getid()}, getqflist({'winid':1}))
1940	cclose
1941    endif
1942
1943    " Invalid arguments
1944    call assert_fails('call g:Xgetlist([])', 'E715')
1945    call assert_fails('call g:Xsetlist([], "a", [])', 'E715')
1946    let s = g:Xsetlist([], 'a', {'abc':1})
1947    call assert_equal(-1, s)
1948
1949    call assert_equal({}, g:Xgetlist({'abc':1}))
1950    call assert_equal('', g:Xgetlist({'nr':99, 'title':1}).title)
1951    call assert_equal('', g:Xgetlist({'nr':[], 'title':1}).title)
1952
1953    if a:cchar == 'l'
1954	call assert_equal({}, getloclist(99, {'title': 1}))
1955    endif
1956
1957    " Context related tests
1958    let s = g:Xsetlist([], 'a', {'context':[1,2,3]})
1959    call assert_equal(0, s)
1960    call test_garbagecollect_now()
1961    let d = g:Xgetlist({'context':1})
1962    call assert_equal([1,2,3], d.context)
1963    call g:Xsetlist([], 'a', {'context':{'color':'green'}})
1964    let d = g:Xgetlist({'context':1})
1965    call assert_equal({'color':'green'}, d.context)
1966    call g:Xsetlist([], 'a', {'context':"Context info"})
1967    let d = g:Xgetlist({'context':1})
1968    call assert_equal("Context info", d.context)
1969    call g:Xsetlist([], 'a', {'context':246})
1970    let d = g:Xgetlist({'context':1})
1971    call assert_equal(246, d.context)
1972    if a:cchar == 'l'
1973	" Test for copying context across two different location lists
1974	new | only
1975	let w1_id = win_getid()
1976	let l = [1]
1977	call setloclist(0, [], 'a', {'context':l})
1978	new
1979	let w2_id = win_getid()
1980	call add(l, 2)
1981	call assert_equal([1, 2], getloclist(w1_id, {'context':1}).context)
1982	call assert_equal([1, 2], getloclist(w2_id, {'context':1}).context)
1983	unlet! l
1984	call assert_equal([1, 2], getloclist(w2_id, {'context':1}).context)
1985	only
1986	call setloclist(0, [], 'f')
1987	call assert_equal('', getloclist(0, {'context':1}).context)
1988    endif
1989
1990    " Test for changing the context of previous quickfix lists
1991    call g:Xsetlist([], 'f')
1992    Xexpr "One"
1993    Xexpr "Two"
1994    Xexpr "Three"
1995    call g:Xsetlist([], 'r', {'context' : [1], 'nr' : 1})
1996    call g:Xsetlist([], 'a', {'context' : [2], 'nr' : 2})
1997    " Also, check for setting the context using quickfix list number zero.
1998    call g:Xsetlist([], 'r', {'context' : [3], 'nr' : 0})
1999    call test_garbagecollect_now()
2000    let l = g:Xgetlist({'nr' : 1, 'context' : 1})
2001    call assert_equal([1], l.context)
2002    let l = g:Xgetlist({'nr' : 2, 'context' : 1})
2003    call assert_equal([2], l.context)
2004    let l = g:Xgetlist({'nr' : 3, 'context' : 1})
2005    call assert_equal([3], l.context)
2006
2007    " Test for changing the context through reference and for garbage
2008    " collection of quickfix context
2009    let l = ["red"]
2010    call g:Xsetlist([], ' ', {'context' : l})
2011    call add(l, "blue")
2012    let x = g:Xgetlist({'context' : 1})
2013    call add(x.context, "green")
2014    call assert_equal(["red", "blue", "green"], l)
2015    call assert_equal(["red", "blue", "green"], x.context)
2016    unlet l
2017    call test_garbagecollect_now()
2018    let m = g:Xgetlist({'context' : 1})
2019    call assert_equal(["red", "blue", "green"], m.context)
2020
2021    " Test for setting/getting items
2022    Xexpr ""
2023    let qfprev = g:Xgetlist({'nr':0})
2024    let s = g:Xsetlist([], ' ', {'title':'Green',
2025		\ 'items' : [{'filename':'F1', 'lnum':10}]})
2026    call assert_equal(0, s)
2027    let qfcur = g:Xgetlist({'nr':0})
2028    call assert_true(qfcur.nr == qfprev.nr + 1)
2029    let l = g:Xgetlist({'items':1})
2030    call assert_equal('F1', bufname(l.items[0].bufnr))
2031    call assert_equal(10, l.items[0].lnum)
2032    call g:Xsetlist([], 'a', {'items' : [{'filename':'F2', 'lnum':20},
2033		\  {'filename':'F2', 'lnum':30}]})
2034    let l = g:Xgetlist({'items':1})
2035    call assert_equal('F2', bufname(l.items[2].bufnr))
2036    call assert_equal(30, l.items[2].lnum)
2037    call g:Xsetlist([], 'r', {'items' : [{'filename':'F3', 'lnum':40}]})
2038    let l = g:Xgetlist({'items':1})
2039    call assert_equal('F3', bufname(l.items[0].bufnr))
2040    call assert_equal(40, l.items[0].lnum)
2041    call g:Xsetlist([], 'r', {'items' : []})
2042    let l = g:Xgetlist({'items':1})
2043    call assert_equal(0, len(l.items))
2044
2045    call g:Xsetlist([], 'r', {'title' : 'TestTitle'})
2046    call g:Xsetlist([], 'r', {'items' : [{'filename' : 'F1', 'lnum' : 10, 'text' : 'L10'}]})
2047    call g:Xsetlist([], 'r', {'items' : [{'filename' : 'F1', 'lnum' : 10, 'text' : 'L10'}]})
2048    call assert_equal('TestTitle', g:Xgetlist({'title' : 1}).title)
2049
2050    " Test for getting id of window associated with a location list window
2051    if a:cchar == 'l'
2052      only
2053      call assert_equal(0, g:Xgetlist({'all' : 1}).filewinid)
2054      let wid = win_getid()
2055      Xopen
2056      call assert_equal(wid, g:Xgetlist({'filewinid' : 1}).filewinid)
2057      wincmd w
2058      call assert_equal(0, g:Xgetlist({'filewinid' : 1}).filewinid)
2059      only
2060    endif
2061
2062    " The following used to crash Vim with address sanitizer
2063    call g:Xsetlist([], 'f')
2064    call g:Xsetlist([], 'a', {'items' : [{'filename':'F1', 'lnum':10}]})
2065    call assert_equal(10, g:Xgetlist({'items':1}).items[0].lnum)
2066
2067    " Try setting the items using a string
2068    call assert_equal(-1, g:Xsetlist([], ' ', {'items' : 'Test'}))
2069
2070    " Save and restore the quickfix stack
2071    call g:Xsetlist([], 'f')
2072    call assert_equal(0, g:Xgetlist({'nr':'$'}).nr)
2073    Xexpr "File1:10:Line1"
2074    Xexpr "File2:20:Line2"
2075    Xexpr "File3:30:Line3"
2076    let last_qf = g:Xgetlist({'nr':'$'}).nr
2077    call assert_equal(3, last_qf)
2078    let qstack = []
2079    for i in range(1, last_qf)
2080	let qstack = add(qstack, g:Xgetlist({'nr':i, 'all':1}))
2081    endfor
2082    call g:Xsetlist([], 'f')
2083    for i in range(len(qstack))
2084	call g:Xsetlist([], ' ', qstack[i])
2085    endfor
2086    call assert_equal(3, g:Xgetlist({'nr':'$'}).nr)
2087    call assert_equal(10, g:Xgetlist({'nr':1, 'items':1}).items[0].lnum)
2088    call assert_equal(20, g:Xgetlist({'nr':2, 'items':1}).items[0].lnum)
2089    call assert_equal(30, g:Xgetlist({'nr':3, 'items':1}).items[0].lnum)
2090    call g:Xsetlist([], 'f')
2091
2092    " Swap two quickfix lists
2093    Xexpr "File1:10:Line10"
2094    Xexpr "File2:20:Line20"
2095    Xexpr "File3:30:Line30"
2096    call g:Xsetlist([], 'r', {'nr':1,'title':'Colors','context':['Colors']})
2097    call g:Xsetlist([], 'r', {'nr':2,'title':'Fruits','context':['Fruits']})
2098    let l1=g:Xgetlist({'nr':1,'all':1})
2099    let l2=g:Xgetlist({'nr':2,'all':1})
2100    let save_id = l1.id
2101    let l1.id=l2.id
2102    let l2.id=save_id
2103    call g:Xsetlist([], 'r', l1)
2104    call g:Xsetlist([], 'r', l2)
2105    let newl1=g:Xgetlist({'nr':1,'all':1})
2106    let newl2=g:Xgetlist({'nr':2,'all':1})
2107    call assert_equal('Fruits', newl1.title)
2108    call assert_equal(['Fruits'], newl1.context)
2109    call assert_equal('Line20', newl1.items[0].text)
2110    call assert_equal('Colors', newl2.title)
2111    call assert_equal(['Colors'], newl2.context)
2112    call assert_equal('Line10', newl2.items[0].text)
2113    call g:Xsetlist([], 'f')
2114endfunc
2115
2116func Test_qf_property()
2117    call Xproperty_tests('c')
2118    call Xproperty_tests('l')
2119endfunc
2120
2121" Test for setting the current index in the location/quickfix list
2122func Xtest_setqfidx(cchar)
2123  call s:setup_commands(a:cchar)
2124
2125  Xgetexpr "F1:10:1:Line1\nF2:20:2:Line2\nF3:30:3:Line3"
2126  Xgetexpr "F4:10:1:Line1\nF5:20:2:Line2\nF6:30:3:Line3"
2127  Xgetexpr "F7:10:1:Line1\nF8:20:2:Line2\nF9:30:3:Line3"
2128
2129  call g:Xsetlist([], 'a', {'nr' : 3, 'idx' : 2})
2130  call g:Xsetlist([], 'a', {'nr' : 2, 'idx' : 2})
2131  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 3})
2132  Xolder 2
2133  Xopen
2134  call assert_equal(3, line('.'))
2135  Xnewer
2136  call assert_equal(2, line('.'))
2137  Xnewer
2138  call assert_equal(2, line('.'))
2139  " Update the current index with the quickfix window open
2140  wincmd w
2141  call g:Xsetlist([], 'a', {'nr' : 3, 'idx' : 3})
2142  Xopen
2143  call assert_equal(3, line('.'))
2144  Xclose
2145
2146  " Set the current index to the last entry
2147  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : '$'})
2148  call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx)
2149  " A large value should set the index to the last index
2150  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 1})
2151  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 999})
2152  call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx)
2153  " Invalid index values
2154  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : -1})
2155  call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx)
2156  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 0})
2157  call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx)
2158  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 'xx'})
2159  call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx)
2160  call assert_fails("call g:Xsetlist([], 'a', {'nr':1, 'idx':[]})", 'E745:')
2161
2162  call g:Xsetlist([], 'f')
2163  new | only
2164endfunc
2165
2166func Test_setqfidx()
2167  call Xtest_setqfidx('c')
2168  call Xtest_setqfidx('l')
2169endfunc
2170
2171" Tests for the QuickFixCmdPre/QuickFixCmdPost autocommands
2172func QfAutoCmdHandler(loc, cmd)
2173  call add(g:acmds, a:loc . a:cmd)
2174endfunc
2175
2176func Test_Autocmd()
2177  autocmd QuickFixCmdPre * call QfAutoCmdHandler('pre', expand('<amatch>'))
2178  autocmd QuickFixCmdPost * call QfAutoCmdHandler('post', expand('<amatch>'))
2179
2180  let g:acmds = []
2181  cexpr "F1:10:Line 10"
2182  caddexpr "F1:20:Line 20"
2183  cgetexpr "F1:30:Line 30"
2184  cexpr ""
2185  caddexpr ""
2186  cgetexpr ""
2187  silent! cexpr non_existing_func()
2188  silent! caddexpr non_existing_func()
2189  silent! cgetexpr non_existing_func()
2190  let l = ['precexpr',
2191	      \ 'postcexpr',
2192	      \ 'precaddexpr',
2193	      \ 'postcaddexpr',
2194	      \ 'precgetexpr',
2195	      \ 'postcgetexpr',
2196	      \ 'precexpr',
2197	      \ 'postcexpr',
2198	      \ 'precaddexpr',
2199	      \ 'postcaddexpr',
2200	      \ 'precgetexpr',
2201	      \ 'postcgetexpr',
2202	      \ 'precexpr',
2203	      \ 'precaddexpr',
2204	      \ 'precgetexpr']
2205  call assert_equal(l, g:acmds)
2206
2207  let g:acmds = []
2208  enew! | call append(0, "F2:10:Line 10")
2209  cbuffer!
2210  enew! | call append(0, "F2:20:Line 20")
2211  cgetbuffer
2212  enew! | call append(0, "F2:30:Line 30")
2213  caddbuffer
2214  new
2215  let bnum = bufnr('%')
2216  bunload
2217  exe 'silent! cbuffer! ' . bnum
2218  exe 'silent! cgetbuffer ' . bnum
2219  exe 'silent! caddbuffer ' . bnum
2220  enew!
2221  let l = ['precbuffer',
2222	      \ 'postcbuffer',
2223	      \ 'precgetbuffer',
2224	      \ 'postcgetbuffer',
2225	      \ 'precaddbuffer',
2226	      \ 'postcaddbuffer',
2227	      \ 'precbuffer',
2228	      \ 'precgetbuffer',
2229	      \ 'precaddbuffer']
2230  call assert_equal(l, g:acmds)
2231
2232  call writefile(['Xtest:1:Line1'], 'Xtest')
2233  call writefile([], 'Xempty')
2234  let g:acmds = []
2235  cfile Xtest
2236  caddfile Xtest
2237  cgetfile Xtest
2238  cfile Xempty
2239  caddfile Xempty
2240  cgetfile Xempty
2241  silent! cfile do_not_exist
2242  silent! caddfile do_not_exist
2243  silent! cgetfile do_not_exist
2244  let l = ['precfile',
2245	      \ 'postcfile',
2246	      \ 'precaddfile',
2247	      \ 'postcaddfile',
2248	      \ 'precgetfile',
2249	      \ 'postcgetfile',
2250	      \ 'precfile',
2251	      \ 'postcfile',
2252	      \ 'precaddfile',
2253	      \ 'postcaddfile',
2254	      \ 'precgetfile',
2255	      \ 'postcgetfile',
2256	      \ 'precfile',
2257	      \ 'postcfile',
2258	      \ 'precaddfile',
2259	      \ 'postcaddfile',
2260	      \ 'precgetfile',
2261	      \ 'postcgetfile']
2262  call assert_equal(l, g:acmds)
2263
2264  let g:acmds = []
2265  helpgrep quickfix
2266  silent! helpgrep non_existing_help_topic
2267  vimgrep test Xtest
2268  vimgrepadd test Xtest
2269  silent! vimgrep non_existing_test Xtest
2270  silent! vimgrepadd non_existing_test Xtest
2271  set makeprg=
2272  silent! make
2273  set makeprg&
2274  let l = ['prehelpgrep',
2275	      \ 'posthelpgrep',
2276	      \ 'prehelpgrep',
2277	      \ 'posthelpgrep',
2278	      \ 'previmgrep',
2279	      \ 'postvimgrep',
2280	      \ 'previmgrepadd',
2281	      \ 'postvimgrepadd',
2282	      \ 'previmgrep',
2283	      \ 'postvimgrep',
2284	      \ 'previmgrepadd',
2285	      \ 'postvimgrepadd',
2286	      \ 'premake',
2287	      \ 'postmake']
2288  call assert_equal(l, g:acmds)
2289
2290  if has('unix')
2291    " Run this test only on Unix-like systems. The grepprg may not be set on
2292    " non-Unix systems.
2293    " The following lines are used for the grep test. Don't remove.
2294    " Grep_Autocmd_Text: Match 1
2295    " GrepAdd_Autocmd_Text: Match 2
2296    let g:acmds = []
2297    silent grep Grep_Autocmd_Text test_quickfix.vim
2298    silent grepadd GrepAdd_Autocmd_Text test_quickfix.vim
2299    silent grep abc123def Xtest
2300    silent grepadd abc123def Xtest
2301    let l = ['pregrep',
2302		\ 'postgrep',
2303		\ 'pregrepadd',
2304		\ 'postgrepadd',
2305		\ 'pregrep',
2306		\ 'postgrep',
2307		\ 'pregrepadd',
2308		\ 'postgrepadd']
2309    call assert_equal(l, g:acmds)
2310  endif
2311
2312  call delete('Xtest')
2313  call delete('Xempty')
2314  au! QuickFixCmdPre
2315  au! QuickFixCmdPost
2316endfunc
2317
2318func Test_Autocmd_Exception()
2319  set efm=%m
2320  lgetexpr '?'
2321
2322  try
2323    call DoesNotExit()
2324  catch
2325    lgetexpr '1'
2326  finally
2327    lgetexpr '1'
2328  endtry
2329
2330  call assert_equal('1', getloclist(0)[0].text)
2331
2332  set efm&vim
2333endfunc
2334
2335func Test_caddbuffer_wrong()
2336  " This used to cause a memory access in freed memory.
2337  let save_efm = &efm
2338  set efm=%EEEE%m,%WWWW,%+CCCC%>%#,%GGGG%.#
2339  cgetexpr ['WWWW', 'EEEE', 'CCCC']
2340  let &efm = save_efm
2341  caddbuffer
2342  bwipe!
2343endfunc
2344
2345func Test_caddexpr_wrong()
2346  " This used to cause a memory access in freed memory.
2347  cbuffer
2348  cbuffer
2349  copen
2350  let save_efm = &efm
2351  set efm=%
2352  call assert_fails('caddexpr ""', 'E376:')
2353  let &efm = save_efm
2354endfunc
2355
2356func Test_dirstack_cleanup()
2357  " This used to cause a memory access in freed memory.
2358  let save_efm = &efm
2359  lexpr '0'
2360  lopen
2361  fun X(c)
2362    let save_efm=&efm
2363    set efm=%D%f
2364    if a:c == 'c'
2365      caddexpr '::'
2366    else
2367      laddexpr ':0:0'
2368    endif
2369    let &efm=save_efm
2370  endfun
2371  call X('c')
2372  call X('l')
2373  call setqflist([], 'r')
2374  caddbuffer
2375  let &efm = save_efm
2376endfunc
2377
2378" Tests for jumping to entries from the location list window and quickfix
2379" window
2380func Test_cwindow_jump()
2381  set efm=%f%%%l%%%m
2382  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2383  lopen | only
2384  lfirst
2385  call assert_true(winnr('$') == 2)
2386  call assert_true(winnr() == 1)
2387  " Location list for the new window should be set
2388  call assert_true(getloclist(0)[2].text == 'Line 30')
2389
2390  " Open a scratch buffer
2391  " Open a new window and create a location list
2392  " Open the location list window and close the other window
2393  " Jump to an entry.
2394  " Should create a new window and jump to the entry. The scratch buffer
2395  " should not be used.
2396  enew | only
2397  set buftype=nofile
2398  below new
2399  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2400  lopen
2401  2wincmd c
2402  lnext
2403  call assert_true(winnr('$') == 3)
2404  call assert_true(winnr() == 2)
2405
2406  " Open two windows with two different location lists
2407  " Open the location list window and close the previous window
2408  " Jump to an entry in the location list window
2409  " Should open the file in the first window and not set the location list.
2410  enew | only
2411  lgetexpr ["F1%5%Line 5"]
2412  below new
2413  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2414  lopen
2415  2wincmd c
2416  lnext
2417  call assert_true(winnr() == 1)
2418  call assert_true(getloclist(0)[0].text == 'Line 5')
2419
2420  enew | only
2421  cgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2422  copen
2423  cnext
2424  call assert_true(winnr('$') == 2)
2425  call assert_true(winnr() == 1)
2426
2427  enew | only
2428  set efm&vim
2429endfunc
2430
2431func XvimgrepTests(cchar)
2432  call s:setup_commands(a:cchar)
2433
2434  call writefile(['Editor:VIM vim',
2435	      \ 'Editor:Emacs EmAcS',
2436	      \ 'Editor:Notepad NOTEPAD'], 'Xtestfile1')
2437  call writefile(['Linux', 'MacOS', 'MS-Windows'], 'Xtestfile2')
2438
2439  " Error cases
2440  call assert_fails('Xvimgrep /abc *', 'E682:')
2441
2442  let @/=''
2443  call assert_fails('Xvimgrep // *', 'E35:')
2444
2445  call assert_fails('Xvimgrep abc', 'E683:')
2446  call assert_fails('Xvimgrep a1b2c3 Xtestfile1', 'E480:')
2447  call assert_fails('Xvimgrep pat Xa1b2c3', 'E480:')
2448
2449  Xexpr ""
2450  Xvimgrepadd Notepad Xtestfile1
2451  Xvimgrepadd MacOS Xtestfile2
2452  let l = g:Xgetlist()
2453  call assert_equal(2, len(l))
2454  call assert_equal('Editor:Notepad NOTEPAD', l[0].text)
2455
2456  Xvimgrep #\cvim#g Xtestfile?
2457  let l = g:Xgetlist()
2458  call assert_equal(2, len(l))
2459  call assert_equal(8, l[0].col)
2460  call assert_equal(12, l[1].col)
2461
2462  1Xvimgrep ?Editor? Xtestfile*
2463  let l = g:Xgetlist()
2464  call assert_equal(1, len(l))
2465  call assert_equal('Editor:VIM vim', l[0].text)
2466
2467  edit +3 Xtestfile2
2468  Xvimgrep +\cemacs+j Xtestfile1
2469  let l = g:Xgetlist()
2470  call assert_equal('Xtestfile2', bufname(''))
2471  call assert_equal('Editor:Emacs EmAcS', l[0].text)
2472
2473  " Test for unloading a buffer after vimgrep searched the buffer
2474  %bwipe
2475  Xvimgrep /Editor/j Xtestfile*
2476  call assert_equal(0, getbufinfo('Xtestfile1')[0].loaded)
2477  call assert_equal([], getbufinfo('Xtestfile2'))
2478
2479  call delete('Xtestfile1')
2480  call delete('Xtestfile2')
2481endfunc
2482
2483" Tests for the :vimgrep command
2484func Test_vimgrep()
2485  call XvimgrepTests('c')
2486  call XvimgrepTests('l')
2487endfunc
2488
2489" Test for incsearch highlighting of the :vimgrep pattern
2490" This test used to cause "E315: ml_get: invalid lnum" errors.
2491func Test_vimgrep_incsearch()
2492  enew
2493  set incsearch
2494  call test_override("char_avail", 1)
2495
2496  call feedkeys(":2vimgrep assert test_quickfix.vim test_cdo.vim\<CR>", "ntx")
2497  let l = getqflist()
2498  call assert_equal(2, len(l))
2499
2500  call test_override("ALL", 0)
2501  set noincsearch
2502endfunc
2503
2504func XfreeTests(cchar)
2505  call s:setup_commands(a:cchar)
2506
2507  enew | only
2508
2509  " Deleting the quickfix stack should work even When the current list is
2510  " somewhere in the middle of the stack
2511  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2512  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2513  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2514  Xolder
2515  call g:Xsetlist([], 'f')
2516  call assert_equal(0, len(g:Xgetlist()))
2517
2518  " After deleting the stack, adding a new list should create a stack with a
2519  " single list.
2520  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2521  call assert_equal(1, g:Xgetlist({'all':1}).nr)
2522
2523  " Deleting the stack from a quickfix window should update/clear the
2524  " quickfix/location list window.
2525  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2526  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2527  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2528  Xolder
2529  Xwindow
2530  call g:Xsetlist([], 'f')
2531  call assert_equal(2, winnr('$'))
2532  call assert_equal(1, line('$'))
2533  Xclose
2534
2535  " Deleting the stack from a non-quickfix window should update/clear the
2536  " quickfix/location list window.
2537  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2538  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2539  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2540  Xolder
2541  Xwindow
2542  wincmd p
2543  call g:Xsetlist([], 'f')
2544  call assert_equal(0, len(g:Xgetlist()))
2545  wincmd p
2546  call assert_equal(2, winnr('$'))
2547  call assert_equal(1, line('$'))
2548
2549  " After deleting the location list stack, if the location list window is
2550  " opened, then a new location list should be created. So opening the
2551  " location list window again should not create a new window.
2552  if a:cchar == 'l'
2553      lexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2554      wincmd p
2555      lopen
2556      call assert_equal(2, winnr('$'))
2557  endif
2558  Xclose
2559endfunc
2560
2561" Tests for the quickfix free functionality
2562func Test_qf_free()
2563  call XfreeTests('c')
2564  call XfreeTests('l')
2565endfunc
2566
2567" Test for buffer overflow when parsing lines and adding new entries to
2568" the quickfix list.
2569func Test_bufoverflow()
2570  set efm=%f:%l:%m
2571  cgetexpr ['File1:100:' . repeat('x', 1025)]
2572
2573  set efm=%+GCompiler:\ %.%#,%f:%l:%m
2574  cgetexpr ['Compiler: ' . repeat('a', 1015), 'File1:10:Hello World']
2575
2576  set efm=%DEntering\ directory\ %f,%f:%l:%m
2577  cgetexpr ['Entering directory ' . repeat('a', 1006),
2578	      \ 'File1:10:Hello World']
2579  set efm&vim
2580endfunc
2581
2582" Tests for getting the quickfix stack size
2583func XsizeTests(cchar)
2584  call s:setup_commands(a:cchar)
2585
2586  call g:Xsetlist([], 'f')
2587  call assert_equal(0, g:Xgetlist({'nr':'$'}).nr)
2588  call assert_equal('', g:Xgetlist({'nr':'$', 'all':1}).title)
2589  call assert_equal(0, g:Xgetlist({'nr':0}).nr)
2590
2591  Xexpr "File1:10:Line1"
2592  Xexpr "File2:20:Line2"
2593  Xexpr "File3:30:Line3"
2594  Xolder | Xolder
2595  call assert_equal(3, g:Xgetlist({'nr':'$'}).nr)
2596  call g:Xsetlist([], 'f')
2597
2598  Xexpr "File1:10:Line1"
2599  Xexpr "File2:20:Line2"
2600  Xexpr "File3:30:Line3"
2601  Xolder | Xolder
2602  call g:Xsetlist([], 'a', {'nr':'$', 'title':'Compiler'})
2603  call assert_equal('Compiler', g:Xgetlist({'nr':3, 'all':1}).title)
2604endfunc
2605
2606func Test_Qf_Size()
2607  call XsizeTests('c')
2608  call XsizeTests('l')
2609endfunc
2610
2611func Test_cclose_from_copen()
2612    augroup QF_Test
2613	au!
2614        au FileType qf :call assert_fails(':cclose', 'E788')
2615    augroup END
2616    copen
2617    augroup QF_Test
2618	au!
2619    augroup END
2620    augroup! QF_Test
2621endfunc
2622
2623func Test_cclose_in_autocmd()
2624  " Problem is only triggered if "starting" is zero, so that the OptionsSet
2625  " event will be triggered.
2626  call test_override('starting', 1)
2627  augroup QF_Test
2628    au!
2629    au FileType qf :call assert_fails(':cclose', 'E788')
2630  augroup END
2631  copen
2632  augroup QF_Test
2633    au!
2634  augroup END
2635  augroup! QF_Test
2636  call test_override('starting', 0)
2637endfunc
2638
2639" Check that ":file" without an argument is possible even when "curbuf_lock"
2640" is set.
2641func Test_file_from_copen()
2642  " Works without argument.
2643  augroup QF_Test
2644    au!
2645    au FileType qf file
2646  augroup END
2647  copen
2648
2649  augroup QF_Test
2650    au!
2651  augroup END
2652  cclose
2653
2654  " Fails with argument.
2655  augroup QF_Test
2656    au!
2657    au FileType qf call assert_fails(':file foo', 'E788')
2658  augroup END
2659  copen
2660  augroup QF_Test
2661    au!
2662  augroup END
2663  cclose
2664
2665  augroup! QF_Test
2666endfunction
2667
2668func Test_resize_from_copen()
2669    augroup QF_Test
2670	au!
2671        au FileType qf resize 5
2672    augroup END
2673    try
2674	" This should succeed without any exception.  No other buffers are
2675	" involved in the autocmd.
2676	copen
2677    finally
2678	augroup QF_Test
2679	    au!
2680	augroup END
2681	augroup! QF_Test
2682    endtry
2683endfunc
2684
2685" Tests for the quickfix buffer b:changedtick variable
2686func Xchangedtick_tests(cchar)
2687  call s:setup_commands(a:cchar)
2688
2689  new | only
2690
2691  Xexpr "" | Xexpr "" | Xexpr ""
2692
2693  Xopen
2694  Xolder
2695  Xolder
2696  Xaddexpr "F1:10:Line10"
2697  Xaddexpr "F2:20:Line20"
2698  call g:Xsetlist([{"filename":"F3", "lnum":30, "text":"Line30"}], 'a')
2699  call g:Xsetlist([], 'f')
2700  call assert_equal(8, getbufvar('%', 'changedtick'))
2701  Xclose
2702endfunc
2703
2704func Test_changedtick()
2705  call Xchangedtick_tests('c')
2706  call Xchangedtick_tests('l')
2707endfunc
2708
2709" Tests for parsing an expression using setqflist()
2710func Xsetexpr_tests(cchar)
2711  call s:setup_commands(a:cchar)
2712
2713  let t = ["File1:10:Line10", "File1:20:Line20"]
2714  call g:Xsetlist([], ' ', {'lines' : t})
2715  call g:Xsetlist([], 'a', {'lines' : ["File1:30:Line30"]})
2716
2717  let l = g:Xgetlist()
2718  call assert_equal(3, len(l))
2719  call assert_equal(20, l[1].lnum)
2720  call assert_equal('Line30', l[2].text)
2721  call g:Xsetlist([], 'r', {'lines' : ["File2:5:Line5"]})
2722  let l = g:Xgetlist()
2723  call assert_equal(1, len(l))
2724  call assert_equal('Line5', l[0].text)
2725  call assert_equal(-1, g:Xsetlist([], 'a', {'lines' : 10}))
2726  call assert_equal(-1, g:Xsetlist([], 'a', {'lines' : "F1:10:L10"}))
2727
2728  call g:Xsetlist([], 'f')
2729  " Add entries to multiple lists
2730  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["File1:10:Line10"]})
2731  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["File2:20:Line20"]})
2732  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["File1:15:Line15"]})
2733  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["File2:25:Line25"]})
2734  call assert_equal('Line15', g:Xgetlist({'nr':1, 'items':1}).items[1].text)
2735  call assert_equal('Line25', g:Xgetlist({'nr':2, 'items':1}).items[1].text)
2736
2737  " Adding entries using a custom efm
2738  set efm&
2739  call g:Xsetlist([], ' ', {'efm' : '%f#%l#%m',
2740				\ 'lines' : ["F1#10#L10", "F2#20#L20"]})
2741  call assert_equal(20, g:Xgetlist({'items':1}).items[1].lnum)
2742  call g:Xsetlist([], 'a', {'efm' : '%f#%l#%m', 'lines' : ["F3:30:L30"]})
2743  call assert_equal('F3:30:L30', g:Xgetlist({'items':1}).items[2].text)
2744  call assert_equal(20, g:Xgetlist({'items':1}).items[1].lnum)
2745  call assert_equal(-1, g:Xsetlist([], 'a', {'efm' : [],
2746				\ 'lines' : ['F1:10:L10']}))
2747endfunc
2748
2749func Test_setexpr()
2750  call Xsetexpr_tests('c')
2751  call Xsetexpr_tests('l')
2752endfunc
2753
2754" Tests for per quickfix/location list directory stack
2755func Xmultidirstack_tests(cchar)
2756  call s:setup_commands(a:cchar)
2757
2758  call g:Xsetlist([], 'f')
2759  Xexpr "" | Xexpr ""
2760
2761  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["Entering dir 'Xone/a'"]})
2762  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["Entering dir 'Xtwo/a'"]})
2763  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["one.txt:3:one one one"]})
2764  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["two.txt:5:two two two"]})
2765
2766  let l1 = g:Xgetlist({'nr':1, 'items':1})
2767  let l2 = g:Xgetlist({'nr':2, 'items':1})
2768  call assert_equal('Xone/a/one.txt', bufname(l1.items[1].bufnr))
2769  call assert_equal(3, l1.items[1].lnum)
2770  call assert_equal('Xtwo/a/two.txt', bufname(l2.items[1].bufnr))
2771  call assert_equal(5, l2.items[1].lnum)
2772endfunc
2773
2774func Test_multidirstack()
2775  call mkdir('Xone/a', 'p')
2776  call mkdir('Xtwo/a', 'p')
2777  let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7']
2778  call writefile(lines, 'Xone/a/one.txt')
2779  call writefile(lines, 'Xtwo/a/two.txt')
2780  let save_efm = &efm
2781  set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f'
2782
2783  call Xmultidirstack_tests('c')
2784  call Xmultidirstack_tests('l')
2785
2786  let &efm = save_efm
2787  call delete('Xone', 'rf')
2788  call delete('Xtwo', 'rf')
2789endfunc
2790
2791" Tests for per quickfix/location list file stack
2792func Xmultifilestack_tests(cchar)
2793  call s:setup_commands(a:cchar)
2794
2795  call g:Xsetlist([], 'f')
2796  Xexpr "" | Xexpr ""
2797
2798  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["[one.txt]"]})
2799  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["[two.txt]"]})
2800  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["(3,5) one one one"]})
2801  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["(5,9) two two two"]})
2802
2803  let l1 = g:Xgetlist({'nr':1, 'items':1})
2804  let l2 = g:Xgetlist({'nr':2, 'items':1})
2805  call assert_equal('one.txt', bufname(l1.items[1].bufnr))
2806  call assert_equal(3, l1.items[1].lnum)
2807  call assert_equal('two.txt', bufname(l2.items[1].bufnr))
2808  call assert_equal(5, l2.items[1].lnum)
2809
2810  " Test for start of a new error line in the same line where a previous
2811  " error line ends with a file stack.
2812  let efm_val = 'Error\ l%l\ in\ %f,'
2813  let efm_val .= '%-P%>(%f%r,Error\ l%l\ in\ %m,%-Q)%r'
2814  let l = g:Xgetlist({'lines' : [
2815	      \ '(one.txt',
2816	      \ 'Error l4 in one.txt',
2817	      \ ') (two.txt',
2818	      \ 'Error l6 in two.txt',
2819	      \ ')',
2820	      \ 'Error l8 in one.txt'
2821	      \ ], 'efm' : efm_val})
2822  call assert_equal(3, len(l.items))
2823  call assert_equal('one.txt', bufname(l.items[0].bufnr))
2824  call assert_equal(4, l.items[0].lnum)
2825  call assert_equal('one.txt', l.items[0].text)
2826  call assert_equal('two.txt', bufname(l.items[1].bufnr))
2827  call assert_equal(6, l.items[1].lnum)
2828  call assert_equal('two.txt', l.items[1].text)
2829  call assert_equal('one.txt', bufname(l.items[2].bufnr))
2830  call assert_equal(8, l.items[2].lnum)
2831  call assert_equal('', l.items[2].text)
2832endfunc
2833
2834func Test_multifilestack()
2835  let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7']
2836  call writefile(lines, 'one.txt')
2837  call writefile(lines, 'two.txt')
2838  let save_efm = &efm
2839  set efm=%+P[%f],(%l\\,%c)\ %m,%-Q
2840
2841  call Xmultifilestack_tests('c')
2842  call Xmultifilestack_tests('l')
2843
2844  let &efm = save_efm
2845  call delete('one.txt')
2846  call delete('two.txt')
2847endfunc
2848
2849" Tests for per buffer 'efm' setting
2850func Test_perbuf_efm()
2851  call writefile(["File1-10-Line10"], 'one.txt')
2852  call writefile(["File2#20#Line20"], 'two.txt')
2853  set efm=%f#%l#%m
2854  new | only
2855  new
2856  setlocal efm=%f-%l-%m
2857  cfile one.txt
2858  wincmd w
2859  caddfile two.txt
2860
2861  let l = getqflist()
2862  call assert_equal(10, l[0].lnum)
2863  call assert_equal('Line20', l[1].text)
2864
2865  set efm&
2866  new | only
2867  call delete('one.txt')
2868  call delete('two.txt')
2869endfunc
2870
2871" Open multiple help windows using ":lhelpgrep
2872" This test used to crash Vim
2873func Test_Multi_LL_Help()
2874    new | only
2875    lhelpgrep window
2876    lopen
2877    e#
2878    lhelpgrep buffer
2879    call assert_equal(3, winnr('$'))
2880    call assert_true(len(getloclist(1)) != 0)
2881    call assert_true(len(getloclist(2)) != 0)
2882    new | only
2883endfunc
2884
2885" Tests for adding new quickfix lists using setqflist()
2886func XaddQf_tests(cchar)
2887  call s:setup_commands(a:cchar)
2888
2889  " Create a new list using ' ' for action
2890  call g:Xsetlist([], 'f')
2891  call g:Xsetlist([], ' ', {'title' : 'Test1'})
2892  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2893  call assert_equal(1, l.nr)
2894  call assert_equal('Test1', l.title)
2895
2896  " Create a new list using ' ' for action and '$' for 'nr'
2897  call g:Xsetlist([], 'f')
2898  call g:Xsetlist([], ' ', {'title' : 'Test2', 'nr' : '$'})
2899  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2900  call assert_equal(1, l.nr)
2901  call assert_equal('Test2', l.title)
2902
2903  " Create a new list using 'a' for action
2904  call g:Xsetlist([], 'f')
2905  call g:Xsetlist([], 'a', {'title' : 'Test3'})
2906  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2907  call assert_equal(1, l.nr)
2908  call assert_equal('Test3', l.title)
2909
2910  " Create a new list using 'a' for action and '$' for 'nr'
2911  call g:Xsetlist([], 'f')
2912  call g:Xsetlist([], 'a', {'title' : 'Test3', 'nr' : '$'})
2913  call g:Xsetlist([], 'a', {'title' : 'Test4'})
2914  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2915  call assert_equal(1, l.nr)
2916  call assert_equal('Test4', l.title)
2917
2918  " Adding a quickfix list should remove all the lists following the current
2919  " list.
2920  Xexpr "" | Xexpr "" | Xexpr ""
2921  silent! 10Xolder
2922  call g:Xsetlist([], ' ', {'title' : 'Test5'})
2923  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2924  call assert_equal(2, l.nr)
2925  call assert_equal('Test5', l.title)
2926
2927  " Add a quickfix list using '$' as the list number.
2928  let lastqf = g:Xgetlist({'nr':'$'}).nr
2929  silent! 99Xolder
2930  call g:Xsetlist([], ' ', {'nr' : '$', 'title' : 'Test6'})
2931  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2932  call assert_equal(lastqf + 1, l.nr)
2933  call assert_equal('Test6', l.title)
2934
2935  " Add a quickfix list using 'nr' set to one more than the quickfix
2936  " list size.
2937  let lastqf = g:Xgetlist({'nr':'$'}).nr
2938  silent! 99Xolder
2939  call g:Xsetlist([], ' ', {'nr' : lastqf + 1, 'title' : 'Test7'})
2940  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2941  call assert_equal(lastqf + 1, l.nr)
2942  call assert_equal('Test7', l.title)
2943
2944  " Add a quickfix list to a stack with 10 lists using 'nr' set to '$'
2945  exe repeat('Xexpr "" |', 9) . 'Xexpr ""'
2946  silent! 99Xolder
2947  call g:Xsetlist([], ' ', {'nr' : '$', 'title' : 'Test8'})
2948  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2949  call assert_equal(10, l.nr)
2950  call assert_equal('Test8', l.title)
2951
2952  " Add a quickfix list using 'nr' set to a value greater than 10
2953  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : 12, 'title' : 'Test9'}))
2954
2955  " Try adding a quickfix list with 'nr' set to a value greater than the
2956  " quickfix list size but less than 10.
2957  call g:Xsetlist([], 'f')
2958  Xexpr "" | Xexpr "" | Xexpr ""
2959  silent! 99Xolder
2960  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : 8, 'title' : 'Test10'}))
2961
2962  " Add a quickfix list using 'nr' set to a some string or list
2963  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : [1,2], 'title' : 'Test11'}))
2964endfunc
2965
2966func Test_add_qf()
2967  call XaddQf_tests('c')
2968  call XaddQf_tests('l')
2969endfunc
2970
2971" Test for getting the quickfix list items from some text without modifying
2972" the quickfix stack
2973func XgetListFromLines(cchar)
2974  call s:setup_commands(a:cchar)
2975  call g:Xsetlist([], 'f')
2976
2977  let l = g:Xgetlist({'lines' : ["File2:20:Line20", "File2:30:Line30"]}).items
2978  call assert_equal(2, len(l))
2979  call assert_equal(30, l[1].lnum)
2980
2981  call assert_equal({}, g:Xgetlist({'lines' : 10}))
2982  call assert_equal({}, g:Xgetlist({'lines' : 'File1:10:Line10'}))
2983  call assert_equal([], g:Xgetlist({'lines' : []}).items)
2984  call assert_equal([], g:Xgetlist({'lines' : [10, 20]}).items)
2985
2986  " Parse text using a custom efm
2987  set efm&
2988  let l = g:Xgetlist({'lines':['File3#30#Line30'], 'efm' : '%f#%l#%m'}).items
2989  call assert_equal('Line30', l[0].text)
2990  let l = g:Xgetlist({'lines':['File3:30:Line30'], 'efm' : '%f-%l-%m'}).items
2991  call assert_equal('File3:30:Line30', l[0].text)
2992  let l = g:Xgetlist({'lines':['File3:30:Line30'], 'efm' : [1,2]})
2993  call assert_equal({}, l)
2994  call assert_fails("call g:Xgetlist({'lines':['abc'], 'efm':'%2'})", 'E376:')
2995  call assert_fails("call g:Xgetlist({'lines':['abc'], 'efm':''})", 'E378:')
2996
2997  " Make sure that the quickfix stack is not modified
2998  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
2999endfunc
3000
3001func Test_get_list_from_lines()
3002  call XgetListFromLines('c')
3003  call XgetListFromLines('l')
3004endfunc
3005
3006" Tests for the quickfix list id
3007func Xqfid_tests(cchar)
3008  call s:setup_commands(a:cchar)
3009
3010  call g:Xsetlist([], 'f')
3011  call assert_equal(0, g:Xgetlist({'id':0}).id)
3012  Xexpr ''
3013  let start_id = g:Xgetlist({'id' : 0}).id
3014  Xexpr '' | Xexpr ''
3015  Xolder
3016  call assert_equal(start_id, g:Xgetlist({'id':0, 'nr':1}).id)
3017  call assert_equal(start_id + 1, g:Xgetlist({'id':0, 'nr':0}).id)
3018  call assert_equal(start_id + 2, g:Xgetlist({'id':0, 'nr':'$'}).id)
3019  call assert_equal(0, g:Xgetlist({'id':0, 'nr':99}).id)
3020  call assert_equal(2, g:Xgetlist({'id':start_id + 1, 'nr':0}).nr)
3021  call assert_equal(0, g:Xgetlist({'id':99, 'nr':0}).id)
3022  call assert_equal(0, g:Xgetlist({'id':"abc", 'nr':0}).id)
3023
3024  call g:Xsetlist([], 'a', {'id':start_id, 'context':[1,2]})
3025  call assert_equal([1,2], g:Xgetlist({'nr':1, 'context':1}).context)
3026  call g:Xsetlist([], 'a', {'id':start_id+1, 'lines':['F1:10:L10']})
3027  call assert_equal('L10', g:Xgetlist({'nr':2, 'items':1}).items[0].text)
3028  call assert_equal(-1, g:Xsetlist([], 'a', {'id':999, 'title':'Vim'}))
3029  call assert_equal(-1, g:Xsetlist([], 'a', {'id':'abc', 'title':'Vim'}))
3030
3031  let qfid = g:Xgetlist({'id':0, 'nr':0})
3032  call g:Xsetlist([], 'f')
3033  call assert_equal(0, g:Xgetlist({'id':qfid, 'nr':0}).id)
3034endfunc
3035
3036func Test_qf_id()
3037  call Xqfid_tests('c')
3038  call Xqfid_tests('l')
3039endfunc
3040
3041func Xqfjump_tests(cchar)
3042  call s:setup_commands(a:cchar)
3043
3044  call writefile(["Line1\tFoo", "Line2"], 'F1')
3045  call writefile(["Line1\tBar", "Line2"], 'F2')
3046  call writefile(["Line1\tBaz", "Line2"], 'F3')
3047
3048  call g:Xsetlist([], 'f')
3049
3050  " Tests for
3051  "   Jumping to a line using a pattern
3052  "   Jumping to a column greater than the last column in a line
3053  "   Jumping to a line greater than the last line in the file
3054  let l = []
3055  for i in range(1, 7)
3056    call add(l, {})
3057  endfor
3058  let l[0].filename='F1'
3059  let l[0].pattern='Line1'
3060  let l[1].filename='F2'
3061  let l[1].pattern='Line1'
3062  let l[2].filename='F3'
3063  let l[2].pattern='Line1'
3064  let l[3].filename='F3'
3065  let l[3].lnum=1
3066  let l[3].col=9
3067  let l[3].vcol=1
3068  let l[4].filename='F3'
3069  let l[4].lnum=99
3070  let l[5].filename='F3'
3071  let l[5].lnum=1
3072  let l[5].col=99
3073  let l[5].vcol=1
3074  let l[6].filename='F3'
3075  let l[6].pattern='abcxyz'
3076
3077  call g:Xsetlist([], ' ', {'items' : l})
3078  Xopen | only
3079  2Xnext
3080  call assert_equal(3, g:Xgetlist({'idx' : 0}).idx)
3081  call assert_equal('F3', bufname('%'))
3082  Xnext
3083  call assert_equal(7, col('.'))
3084  Xnext
3085  call assert_equal(2, line('.'))
3086  Xnext
3087  call assert_equal(9, col('.'))
3088  2
3089  Xnext
3090  call assert_equal(2, line('.'))
3091
3092  if a:cchar == 'l'
3093    " When jumping to a location list entry in the location list window and
3094    " no usable windows are available, then a new window should be opened.
3095    enew! | new | only
3096    call g:Xsetlist([], 'f')
3097    setlocal buftype=nofile
3098    new
3099    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']})
3100    Xopen
3101    let winid = win_getid()
3102    wincmd p
3103    close
3104    call win_gotoid(winid)
3105    Xnext
3106    call assert_equal(3, winnr('$'))
3107    call assert_equal(1, winnr())
3108    call assert_equal(2, line('.'))
3109
3110    " When jumping to an entry in the location list window and the window
3111    " associated with the location list is not present and a window containing
3112    " the file is already present, then that window should be used.
3113    close
3114    belowright new
3115    call g:Xsetlist([], 'f')
3116    edit F3
3117    call win_gotoid(winid)
3118    Xlast
3119    call assert_equal(3, winnr())
3120    call assert_equal(6, g:Xgetlist({'size' : 1}).size)
3121    call assert_equal(winid, g:Xgetlist({'winid' : 1}).winid)
3122  endif
3123
3124  " Cleanup
3125  enew!
3126  new | only
3127
3128  call delete('F1')
3129  call delete('F2')
3130  call delete('F3')
3131endfunc
3132
3133func Test_qfjump()
3134  call Xqfjump_tests('c')
3135  call Xqfjump_tests('l')
3136endfunc
3137
3138" Tests for the getqflist() and getloclist() functions when the list is not
3139" present or is empty
3140func Xgetlist_empty_tests(cchar)
3141  call s:setup_commands(a:cchar)
3142
3143  " Empty quickfix stack
3144  call g:Xsetlist([], 'f')
3145  call assert_equal('', g:Xgetlist({'context' : 0}).context)
3146  call assert_equal(0, g:Xgetlist({'id' : 0}).id)
3147  call assert_equal(0, g:Xgetlist({'idx' : 0}).idx)
3148  call assert_equal([], g:Xgetlist({'items' : 0}).items)
3149  call assert_equal(0, g:Xgetlist({'nr' : 0}).nr)
3150  call assert_equal(0, g:Xgetlist({'size' : 0}).size)
3151  call assert_equal('', g:Xgetlist({'title' : 0}).title)
3152  call assert_equal(0, g:Xgetlist({'winid' : 0}).winid)
3153  call assert_equal(0, g:Xgetlist({'changedtick' : 0}).changedtick)
3154  if a:cchar == 'c'
3155    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0,
3156		  \ 'items' : [], 'nr' : 0, 'size' : 0, 'qfbufnr' : 0,
3157		  \ 'title' : '', 'winid' : 0, 'changedtick': 0},
3158		  \ g:Xgetlist({'all' : 0}))
3159  else
3160    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0,
3161		\ 'items' : [], 'nr' : 0, 'size' : 0, 'title' : '',
3162		\ 'winid' : 0, 'changedtick': 0, 'filewinid' : 0,
3163		\ 'qfbufnr' : 0},
3164		\ g:Xgetlist({'all' : 0}))
3165  endif
3166
3167  " Quickfix window with empty stack
3168  silent! Xopen
3169  let qfwinid = (a:cchar == 'c') ? win_getid() : 0
3170  let qfbufnr = (a:cchar == 'c') ? bufnr('') : 0
3171  call assert_equal(qfwinid, g:Xgetlist({'winid' : 0}).winid)
3172  Xclose
3173
3174  " Empty quickfix list
3175  Xexpr ""
3176  call assert_equal('', g:Xgetlist({'context' : 0}).context)
3177  call assert_notequal(0, g:Xgetlist({'id' : 0}).id)
3178  call assert_equal(0, g:Xgetlist({'idx' : 0}).idx)
3179  call assert_equal([], g:Xgetlist({'items' : 0}).items)
3180  call assert_notequal(0, g:Xgetlist({'nr' : 0}).nr)
3181  call assert_equal(0, g:Xgetlist({'size' : 0}).size)
3182  call assert_notequal('', g:Xgetlist({'title' : 0}).title)
3183  call assert_equal(0, g:Xgetlist({'winid' : 0}).winid)
3184  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3185
3186  let qfid = g:Xgetlist({'id' : 0}).id
3187  call g:Xsetlist([], 'f')
3188
3189  " Non-existing quickfix identifier
3190  call assert_equal('', g:Xgetlist({'id' : qfid, 'context' : 0}).context)
3191  call assert_equal(0, g:Xgetlist({'id' : qfid}).id)
3192  call assert_equal(0, g:Xgetlist({'id' : qfid, 'idx' : 0}).idx)
3193  call assert_equal([], g:Xgetlist({'id' : qfid, 'items' : 0}).items)
3194  call assert_equal(0, g:Xgetlist({'id' : qfid, 'nr' : 0}).nr)
3195  call assert_equal(0, g:Xgetlist({'id' : qfid, 'size' : 0}).size)
3196  call assert_equal('', g:Xgetlist({'id' : qfid, 'title' : 0}).title)
3197  call assert_equal(0, g:Xgetlist({'id' : qfid, 'winid' : 0}).winid)
3198  call assert_equal(0, g:Xgetlist({'id' : qfid, 'changedtick' : 0}).changedtick)
3199  if a:cchar == 'c'
3200    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
3201		\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
3202		\ 'qfbufnr' : qfbufnr,
3203		\ 'changedtick' : 0}, g:Xgetlist({'id' : qfid, 'all' : 0}))
3204  else
3205    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
3206		\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
3207		\ 'changedtick' : 0, 'filewinid' : 0, 'qfbufnr' : 0},
3208		\ g:Xgetlist({'id' : qfid, 'all' : 0}))
3209  endif
3210
3211  " Non-existing quickfix list number
3212  call assert_equal('', g:Xgetlist({'nr' : 5, 'context' : 0}).context)
3213  call assert_equal(0, g:Xgetlist({'nr' : 5}).nr)
3214  call assert_equal(0, g:Xgetlist({'nr' : 5, 'idx' : 0}).idx)
3215  call assert_equal([], g:Xgetlist({'nr' : 5, 'items' : 0}).items)
3216  call assert_equal(0, g:Xgetlist({'nr' : 5, 'id' : 0}).id)
3217  call assert_equal(0, g:Xgetlist({'nr' : 5, 'size' : 0}).size)
3218  call assert_equal('', g:Xgetlist({'nr' : 5, 'title' : 0}).title)
3219  call assert_equal(0, g:Xgetlist({'nr' : 5, 'winid' : 0}).winid)
3220  call assert_equal(0, g:Xgetlist({'nr' : 5, 'changedtick' : 0}).changedtick)
3221  if a:cchar == 'c'
3222    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
3223		\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
3224		\ 'changedtick' : 0, 'qfbufnr' : qfbufnr},
3225		\ g:Xgetlist({'nr' : 5, 'all' : 0}))
3226  else
3227    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
3228		\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
3229		\ 'changedtick' : 0, 'filewinid' : 0, 'qfbufnr' : 0},
3230		\ g:Xgetlist({'nr' : 5, 'all' : 0}))
3231  endif
3232endfunc
3233
3234func Test_getqflist()
3235  call Xgetlist_empty_tests('c')
3236  call Xgetlist_empty_tests('l')
3237endfunc
3238
3239func Test_getqflist_invalid_nr()
3240  " The following commands used to crash Vim
3241  cexpr ""
3242  call getqflist({'nr' : $XXX_DOES_NOT_EXIST_XXX})
3243
3244  " Cleanup
3245  call setqflist([], 'r')
3246endfunc
3247
3248" Tests for the quickfix/location list changedtick
3249func Xqftick_tests(cchar)
3250  call s:setup_commands(a:cchar)
3251
3252  call g:Xsetlist([], 'f')
3253
3254  Xexpr "F1:10:Line10"
3255  let qfid = g:Xgetlist({'id' : 0}).id
3256  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3257  Xaddexpr "F2:20:Line20\nF2:21:Line21"
3258  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
3259  call g:Xsetlist([], 'a', {'lines' : ["F3:30:Line30", "F3:31:Line31"]})
3260  call assert_equal(3, g:Xgetlist({'changedtick' : 0}).changedtick)
3261  call g:Xsetlist([], 'r', {'lines' : ["F4:40:Line40"]})
3262  call assert_equal(4, g:Xgetlist({'changedtick' : 0}).changedtick)
3263  call g:Xsetlist([], 'a', {'title' : 'New Title'})
3264  call assert_equal(5, g:Xgetlist({'changedtick' : 0}).changedtick)
3265
3266  enew!
3267  call append(0, ["F5:50:L50", "F6:60:L60"])
3268  Xaddbuffer
3269  call assert_equal(6, g:Xgetlist({'changedtick' : 0}).changedtick)
3270  enew!
3271
3272  call g:Xsetlist([], 'a', {'context' : {'bus' : 'pci'}})
3273  call assert_equal(7, g:Xgetlist({'changedtick' : 0}).changedtick)
3274  call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'},
3275	      \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], 'a')
3276  call assert_equal(8, g:Xgetlist({'changedtick' : 0}).changedtick)
3277  call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'},
3278	      \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], ' ')
3279  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3280  call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'},
3281	      \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], 'r')
3282  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
3283
3284  call writefile(["F8:80:L80", "F8:81:L81"], "Xone")
3285  Xfile Xone
3286  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3287  Xaddfile Xone
3288  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
3289
3290  " Test case for updating a non-current quickfix list
3291  call g:Xsetlist([], 'f')
3292  Xexpr "F1:1:L1"
3293  Xexpr "F2:2:L2"
3294  call g:Xsetlist([], 'a', {'nr' : 1, "lines" : ["F10:10:L10"]})
3295  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3296  call assert_equal(2, g:Xgetlist({'nr' : 1, 'changedtick' : 0}).changedtick)
3297
3298  call delete("Xone")
3299endfunc
3300
3301func Test_qf_tick()
3302  call Xqftick_tests('c')
3303  call Xqftick_tests('l')
3304endfunc
3305
3306" Test helpgrep with lang specifier
3307func Xtest_helpgrep_with_lang_specifier(cchar)
3308  call s:setup_commands(a:cchar)
3309  Xhelpgrep Vim@en
3310  call assert_equal('help', &filetype)
3311  call assert_notequal(0, g:Xgetlist({'nr' : '$'}).nr)
3312  new | only
3313endfunc
3314
3315func Test_helpgrep_with_lang_specifier()
3316  call Xtest_helpgrep_with_lang_specifier('c')
3317  call Xtest_helpgrep_with_lang_specifier('l')
3318endfunc
3319
3320" The following test used to crash Vim.
3321" Open the location list window and close the regular window associated with
3322" the location list. When the garbage collection runs now, it incorrectly
3323" marks the location list context as not in use and frees the context.
3324func Test_ll_window_ctx()
3325  call setloclist(0, [], 'f')
3326  call setloclist(0, [], 'a', {'context' : []})
3327  lopen | only
3328  call test_garbagecollect_now()
3329  echo getloclist(0, {'context' : 1}).context
3330  enew | only
3331endfunc
3332
3333" The following test used to crash vim
3334func Test_lfile_crash()
3335  sp Xtest
3336  au QuickFixCmdPre * bw
3337  call assert_fails('lfile', 'E40')
3338  au! QuickFixCmdPre
3339endfunc
3340
3341" The following test used to crash vim
3342func Test_lbuffer_crash()
3343  sv Xtest
3344  augroup QF_Test
3345    au!
3346    au * * bw
3347  augroup END
3348  lbuffer
3349  augroup QF_Test
3350    au!
3351  augroup END
3352endfunc
3353
3354" The following test used to crash vim
3355func Test_lexpr_crash()
3356  augroup QF_Test
3357    au!
3358    au * * call setloclist(0, [], 'f')
3359  augroup END
3360  lexpr ""
3361  augroup QF_Test
3362    au!
3363  augroup END
3364
3365  enew | only
3366  augroup QF_Test
3367    au!
3368    au BufNew * call setloclist(0, [], 'f')
3369  augroup END
3370  lexpr 'x:1:x'
3371  augroup QF_Test
3372    au!
3373  augroup END
3374
3375  enew | only
3376  lexpr ''
3377  lopen
3378  augroup QF_Test
3379    au!
3380    au FileType * call setloclist(0, [], 'f')
3381  augroup END
3382  lexpr ''
3383  augroup QF_Test
3384    au!
3385  augroup END
3386endfunc
3387
3388" The following test used to crash Vim
3389func Test_lvimgrep_crash()
3390  sv Xtest
3391  augroup QF_Test
3392    au!
3393    au * * call setloclist(0, [], 'f')
3394  augroup END
3395  lvimgrep quickfix test_quickfix.vim
3396  augroup QF_Test
3397    au!
3398  augroup END
3399
3400  new | only
3401  augroup QF_Test
3402    au!
3403    au BufEnter * call setloclist(0, [], 'r')
3404  augroup END
3405  call assert_fails('lvimgrep Test_lvimgrep_crash *', 'E926:')
3406  augroup QF_Test
3407    au!
3408  augroup END
3409
3410  enew | only
3411endfunc
3412
3413" Test for the position of the quickfix and location list window
3414func Test_qfwin_pos()
3415  " Open two windows
3416  new | only
3417  new
3418  cexpr ['F1:10:L10']
3419  copen
3420  " Quickfix window should be the bottom most window
3421  call assert_equal(3, winnr())
3422  close
3423  " Open at the very top
3424  wincmd t
3425  topleft copen
3426  call assert_equal(1, winnr())
3427  close
3428  " open left of the current window
3429  wincmd t
3430  below new
3431  leftabove copen
3432  call assert_equal(2, winnr())
3433  close
3434  " open right of the current window
3435  rightbelow copen
3436  call assert_equal(3, winnr())
3437  close
3438endfunc
3439
3440" Tests for quickfix/location lists changed by autocommands when
3441" :vimgrep/:lvimgrep commands are running.
3442func Test_vimgrep_autocmd()
3443  call setqflist([], 'f')
3444  call writefile(['stars'], 'Xtest1.txt')
3445  call writefile(['stars'], 'Xtest2.txt')
3446
3447  " Test 1:
3448  " When searching for a pattern using :vimgrep, if the quickfix list is
3449  " changed by an autocmd, the results should be added to the correct quickfix
3450  " list.
3451  autocmd BufRead Xtest2.txt cexpr '' | cexpr ''
3452  silent vimgrep stars Xtest*.txt
3453  call assert_equal(1, getqflist({'nr' : 0}).nr)
3454  call assert_equal(3, getqflist({'nr' : '$'}).nr)
3455  call assert_equal('Xtest2.txt', bufname(getqflist()[1].bufnr))
3456  au! BufRead Xtest2.txt
3457
3458  " Test 2:
3459  " When searching for a pattern using :vimgrep, if the quickfix list is
3460  " freed, then a error should be given.
3461  silent! %bwipe!
3462  call setqflist([], 'f')
3463  autocmd BufRead Xtest2.txt for i in range(10) | cexpr '' | endfor
3464  call assert_fails('vimgrep stars Xtest*.txt', 'E925:')
3465  au! BufRead Xtest2.txt
3466
3467  " Test 3:
3468  " When searching for a pattern using :lvimgrep, if the location list is
3469  " freed, then the command should error out.
3470  silent! %bwipe!
3471  let g:save_winid = win_getid()
3472  autocmd BufRead Xtest2.txt call setloclist(g:save_winid, [], 'f')
3473  call assert_fails('lvimgrep stars Xtest*.txt', 'E926:')
3474  au! BufRead Xtest2.txt
3475
3476  call delete('Xtest1.txt')
3477  call delete('Xtest2.txt')
3478  call setqflist([], 'f')
3479endfunc
3480
3481" The following test used to crash Vim
3482func Test_lhelpgrep_autocmd()
3483  lhelpgrep quickfix
3484  autocmd QuickFixCmdPost * call setloclist(0, [], 'f')
3485  lhelpgrep buffer
3486  call assert_equal('help', &filetype)
3487  call assert_equal(0, getloclist(0, {'nr' : '$'}).nr)
3488  lhelpgrep tabpage
3489  call assert_equal('help', &filetype)
3490  call assert_equal(1, getloclist(0, {'nr' : '$'}).nr)
3491  au! QuickFixCmdPost
3492
3493  new | only
3494  augroup QF_Test
3495    au!
3496    au BufEnter * call setqflist([], 'f')
3497  augroup END
3498  call assert_fails('helpgrep quickfix', 'E925:')
3499  augroup QF_Test
3500    au! BufEnter
3501  augroup END
3502
3503  new | only
3504  augroup QF_Test
3505    au!
3506    au BufEnter * call setqflist([], 'r')
3507  augroup END
3508  call assert_fails('helpgrep quickfix', 'E925:')
3509  augroup QF_Test
3510    au! BufEnter
3511  augroup END
3512
3513  new | only
3514  augroup QF_Test
3515    au!
3516    au BufEnter * call setloclist(0, [], 'r')
3517  augroup END
3518  call assert_fails('lhelpgrep quickfix', 'E926:')
3519  augroup QF_Test
3520    au! BufEnter
3521  augroup END
3522
3523  new | only
3524endfunc
3525
3526" Test for shortening/simplifying the file name when opening the
3527" quickfix window or when displaying the quickfix list
3528func Test_shorten_fname()
3529  if !has('unix')
3530    return
3531  endif
3532  %bwipe
3533  " Create a quickfix list with a absolute path filename
3534  let fname = getcwd() . '/test_quickfix.vim'
3535  call setqflist([], ' ', {'lines':[fname . ":20:Line20"], 'efm':'%f:%l:%m'})
3536  call assert_equal(fname, bufname('test_quickfix.vim'))
3537  " Opening the quickfix window should simplify the file path
3538  cwindow
3539  call assert_equal('test_quickfix.vim', bufname('test_quickfix.vim'))
3540  cclose
3541  %bwipe
3542  " Create a quickfix list with a absolute path filename
3543  call setqflist([], ' ', {'lines':[fname . ":20:Line20"], 'efm':'%f:%l:%m'})
3544  call assert_equal(fname, bufname('test_quickfix.vim'))
3545  " Displaying the quickfix list should simplify the file path
3546  silent! clist
3547  call assert_equal('test_quickfix.vim', bufname('test_quickfix.vim'))
3548endfunc
3549
3550" Quickfix title tests
3551" In the below tests, 'exe "cmd"' is used to invoke the quickfix commands.
3552" Otherwise due to indentation, the title is set with spaces at the beginning
3553" of the command.
3554func Test_qftitle()
3555  call writefile(["F1:1:Line1"], 'Xerr')
3556
3557  " :cexpr
3558  exe "cexpr readfile('Xerr')"
3559  call assert_equal(":cexpr readfile('Xerr')", getqflist({'title' : 1}).title)
3560
3561  " :cgetexpr
3562  exe "cgetexpr readfile('Xerr')"
3563  call assert_equal(":cgetexpr readfile('Xerr')",
3564					\ getqflist({'title' : 1}).title)
3565
3566  " :caddexpr
3567  call setqflist([], 'f')
3568  exe "caddexpr readfile('Xerr')"
3569  call assert_equal(":caddexpr readfile('Xerr')",
3570					\ getqflist({'title' : 1}).title)
3571
3572  " :cbuffer
3573  new Xerr
3574  exe "cbuffer"
3575  call assert_equal(':cbuffer (Xerr)', getqflist({'title' : 1}).title)
3576
3577  " :cgetbuffer
3578  edit Xerr
3579  exe "cgetbuffer"
3580  call assert_equal(':cgetbuffer (Xerr)', getqflist({'title' : 1}).title)
3581
3582  " :caddbuffer
3583  call setqflist([], 'f')
3584  edit Xerr
3585  exe "caddbuffer"
3586  call assert_equal(':caddbuffer (Xerr)', getqflist({'title' : 1}).title)
3587
3588  " :cfile
3589  exe "cfile Xerr"
3590  call assert_equal(':cfile Xerr', getqflist({'title' : 1}).title)
3591
3592  " :cgetfile
3593  exe "cgetfile Xerr"
3594  call assert_equal(':cgetfile Xerr', getqflist({'title' : 1}).title)
3595
3596  " :caddfile
3597  call setqflist([], 'f')
3598  exe "caddfile Xerr"
3599  call assert_equal(':caddfile Xerr', getqflist({'title' : 1}).title)
3600
3601  " :grep
3602  set grepprg=internal
3603  exe "grep F1 Xerr"
3604  call assert_equal(':grep F1 Xerr', getqflist({'title' : 1}).title)
3605
3606  " :grepadd
3607  call setqflist([], 'f')
3608  exe "grepadd F1 Xerr"
3609  call assert_equal(':grepadd F1 Xerr', getqflist({'title' : 1}).title)
3610  set grepprg&vim
3611
3612  " :vimgrep
3613  exe "vimgrep F1 Xerr"
3614  call assert_equal(':vimgrep F1 Xerr', getqflist({'title' : 1}).title)
3615
3616  " :vimgrepadd
3617  call setqflist([], 'f')
3618  exe "vimgrepadd F1 Xerr"
3619  call assert_equal(':vimgrepadd F1 Xerr', getqflist({'title' : 1}).title)
3620
3621  call setqflist(['F1:10:L10'], ' ')
3622  call assert_equal(':setqflist()', getqflist({'title' : 1}).title)
3623
3624  call setqflist([], 'f')
3625  call setqflist(['F1:10:L10'], 'a')
3626  call assert_equal(':setqflist()', getqflist({'title' : 1}).title)
3627
3628  call setqflist([], 'f')
3629  call setqflist(['F1:10:L10'], 'r')
3630  call assert_equal(':setqflist()', getqflist({'title' : 1}).title)
3631
3632  close
3633  call delete('Xerr')
3634
3635  call setqflist([], ' ', {'title' : 'Errors'})
3636  copen
3637  call assert_equal('Errors', w:quickfix_title)
3638  call setqflist([], 'r', {'items' : [{'filename' : 'a.c', 'lnum' : 10}]})
3639  call assert_equal('Errors', w:quickfix_title)
3640  cclose
3641endfunc
3642
3643func Test_lbuffer_with_bwipe()
3644  new
3645  new
3646  augroup nasty
3647    au * * bwipe
3648  augroup END
3649  lbuffer
3650  augroup nasty
3651    au!
3652  augroup END
3653endfunc
3654
3655" Test for an autocmd freeing the quickfix/location list when cexpr/lexpr is
3656" running
3657func Xexpr_acmd_freelist(cchar)
3658  call s:setup_commands(a:cchar)
3659
3660  " This was using freed memory.
3661  augroup nasty
3662    au * * call g:Xsetlist([], 'f')
3663  augroup END
3664  Xexpr "x"
3665  augroup nasty
3666    au!
3667  augroup END
3668endfunc
3669
3670func Test_cexpr_acmd_freelist()
3671  call Xexpr_acmd_freelist('c')
3672  call Xexpr_acmd_freelist('l')
3673endfunc
3674
3675" Test for commands that create a new quickfix/location list and jump to the
3676" first error automatically.
3677func Xjumpto_first_error_test(cchar)
3678  call s:setup_commands(a:cchar)
3679
3680  call s:create_test_file('Xtestfile1')
3681  call s:create_test_file('Xtestfile2')
3682  let l = ['Xtestfile1:2:Line2', 'Xtestfile2:4:Line4']
3683
3684  " Test for cexpr/lexpr
3685  enew
3686  Xexpr l
3687  call assert_equal('Xtestfile1', bufname(''))
3688  call assert_equal(2, line('.'))
3689
3690  " Test for cfile/lfile
3691  enew
3692  call writefile(l, 'Xerr')
3693  Xfile Xerr
3694  call assert_equal('Xtestfile1', bufname(''))
3695  call assert_equal(2, line('.'))
3696
3697  " Test for cbuffer/lbuffer
3698  edit Xerr
3699  Xbuffer
3700  call assert_equal('Xtestfile1', bufname(''))
3701  call assert_equal(2, line('.'))
3702
3703  call delete('Xerr')
3704  call delete('Xtestfile1')
3705  call delete('Xtestfile2')
3706endfunc
3707
3708func Test_jumpto_first_error()
3709  call Xjumpto_first_error_test('c')
3710  call Xjumpto_first_error_test('l')
3711endfunc
3712
3713" Test for a quickfix autocmd changing the quickfix/location list before
3714" jumping to the first error in the new list.
3715func Xautocmd_changelist(cchar)
3716  call s:setup_commands(a:cchar)
3717
3718  " Test for cfile/lfile
3719  call s:create_test_file('Xtestfile1')
3720  call s:create_test_file('Xtestfile2')
3721  Xexpr 'Xtestfile1:2:Line2'
3722  autocmd QuickFixCmdPost * Xolder
3723  call writefile(['Xtestfile2:4:Line4'], 'Xerr')
3724  Xfile Xerr
3725  call assert_equal('Xtestfile2', bufname(''))
3726  call assert_equal(4, line('.'))
3727  autocmd! QuickFixCmdPost
3728
3729  " Test for cbuffer/lbuffer
3730  call g:Xsetlist([], 'f')
3731  Xexpr 'Xtestfile1:2:Line2'
3732  autocmd QuickFixCmdPost * Xolder
3733  call writefile(['Xtestfile2:4:Line4'], 'Xerr')
3734  edit Xerr
3735  Xbuffer
3736  call assert_equal('Xtestfile2', bufname(''))
3737  call assert_equal(4, line('.'))
3738  autocmd! QuickFixCmdPost
3739
3740  " Test for cexpr/lexpr
3741  call g:Xsetlist([], 'f')
3742  Xexpr 'Xtestfile1:2:Line2'
3743  autocmd QuickFixCmdPost * Xolder
3744  Xexpr 'Xtestfile2:4:Line4'
3745  call assert_equal('Xtestfile2', bufname(''))
3746  call assert_equal(4, line('.'))
3747  autocmd! QuickFixCmdPost
3748
3749  " The grepprg may not be set on non-Unix systems
3750  if has('unix')
3751    " Test for grep/lgrep
3752    call g:Xsetlist([], 'f')
3753    Xexpr 'Xtestfile1:2:Line2'
3754    autocmd QuickFixCmdPost * Xolder
3755    silent Xgrep Line5 Xtestfile2
3756    call assert_equal('Xtestfile2', bufname(''))
3757    call assert_equal(5, line('.'))
3758    autocmd! QuickFixCmdPost
3759  endif
3760
3761  " Test for vimgrep/lvimgrep
3762  call g:Xsetlist([], 'f')
3763  Xexpr 'Xtestfile1:2:Line2'
3764  autocmd QuickFixCmdPost * Xolder
3765  silent Xvimgrep Line5 Xtestfile2
3766  call assert_equal('Xtestfile2', bufname(''))
3767  call assert_equal(5, line('.'))
3768  autocmd! QuickFixCmdPost
3769
3770  " Test for autocommands clearing the quickfix list before jumping to the
3771  " first error. This should not result in an error
3772  autocmd QuickFixCmdPost * call g:Xsetlist([], 'r')
3773  let v:errmsg = ''
3774  " Test for cfile/lfile
3775  Xfile Xerr
3776  call assert_true(v:errmsg !~# 'E42:')
3777  " Test for cbuffer/lbuffer
3778  edit Xerr
3779  Xbuffer
3780  call assert_true(v:errmsg !~# 'E42:')
3781  " Test for cexpr/lexpr
3782  Xexpr 'Xtestfile2:4:Line4'
3783  call assert_true(v:errmsg !~# 'E42:')
3784  " Test for grep/lgrep
3785  " The grepprg may not be set on non-Unix systems
3786  if has('unix')
3787    silent Xgrep Line5 Xtestfile2
3788    call assert_true(v:errmsg !~# 'E42:')
3789  endif
3790  " Test for vimgrep/lvimgrep
3791  call assert_fails('silent Xvimgrep Line5 Xtestfile2', 'E480:')
3792  autocmd! QuickFixCmdPost
3793
3794  call delete('Xerr')
3795  call delete('Xtestfile1')
3796  call delete('Xtestfile2')
3797endfunc
3798
3799func Test_autocmd_changelist()
3800  call Xautocmd_changelist('c')
3801  call Xautocmd_changelist('l')
3802endfunc
3803
3804" Tests for the ':filter /pat/ clist' command
3805func Test_filter_clist()
3806  cexpr ['Xfile1:10:10:Line 10', 'Xfile2:15:15:Line 15']
3807  call assert_equal([' 2 Xfile2:15 col 15: Line 15'],
3808			\ split(execute('filter /Line 15/ clist'), "\n"))
3809  call assert_equal([' 1 Xfile1:10 col 10: Line 10'],
3810			\ split(execute('filter /Xfile1/ clist'), "\n"))
3811  call assert_equal([], split(execute('filter /abc/ clist'), "\n"))
3812
3813  call setqflist([{'module' : 'abc', 'pattern' : 'pat1'},
3814			\ {'module' : 'pqr', 'pattern' : 'pat2'}], ' ')
3815  call assert_equal([' 2 pqr:pat2:  '],
3816			\ split(execute('filter /pqr/ clist'), "\n"))
3817  call assert_equal([' 1 abc:pat1:  '],
3818			\ split(execute('filter /pat1/ clist'), "\n"))
3819endfunc
3820
3821" Tests for the "CTRL-W <CR>" command.
3822func Xview_result_split_tests(cchar)
3823  call s:setup_commands(a:cchar)
3824
3825  " Test that "CTRL-W <CR>" in a qf/ll window fails with empty list.
3826  call g:Xsetlist([])
3827  Xopen
3828  let l:win_count = winnr('$')
3829  call assert_fails('execute "normal! \<C-W>\<CR>"', 'E42')
3830  call assert_equal(l:win_count, winnr('$'))
3831  Xclose
3832endfunc
3833
3834func Test_view_result_split()
3835  call Xview_result_split_tests('c')
3836  call Xview_result_split_tests('l')
3837endfunc
3838
3839" Test that :cc sets curswant
3840func Test_curswant()
3841  helpgrep quickfix
3842  normal! llll
3843  1cc
3844  call assert_equal(getcurpos()[4], virtcol('.'))
3845  cclose | helpclose
3846endfunc
3847
3848" Test for opening a file from the quickfix window using CTRL-W <Enter>
3849" doesn't leave an empty buffer around.
3850func Test_splitview()
3851  call s:create_test_file('Xtestfile1')
3852  call s:create_test_file('Xtestfile2')
3853  new | only
3854  let last_bufnr = bufnr('Test_sv_1', 1)
3855  let l = ['Xtestfile1:2:Line2', 'Xtestfile2:4:Line4']
3856  cgetexpr l
3857  copen
3858  let numbufs = len(getbufinfo())
3859  exe "normal \<C-W>\<CR>"
3860  copen
3861  exe "normal j\<C-W>\<CR>"
3862  " Make sure new empty buffers are not created
3863  call assert_equal(numbufs, len(getbufinfo()))
3864  " Creating a new buffer should use the next available buffer number
3865  call assert_equal(last_bufnr + 4, bufnr("Test_sv_2", 1))
3866  bwipe Test_sv_1
3867  bwipe Test_sv_2
3868  new | only
3869
3870  " When split opening files from location list window, make sure that two
3871  " windows doesn't refer to the same location list
3872  lgetexpr l
3873  let locid = getloclist(0, {'id' : 0}).id
3874  lopen
3875  exe "normal \<C-W>\<CR>"
3876  call assert_notequal(locid, getloclist(0, {'id' : 0}).id)
3877  call assert_equal(0, getloclist(0, {'winid' : 0}).winid)
3878  new | only
3879
3880  " When split opening files from a helpgrep location list window, a new help
3881  " window should be opened with a copy of the location list.
3882  lhelpgrep window
3883  let locid = getloclist(0, {'id' : 0}).id
3884  lwindow
3885  exe "normal j\<C-W>\<CR>"
3886  call assert_notequal(locid, getloclist(0, {'id' : 0}).id)
3887  call assert_equal(0, getloclist(0, {'winid' : 0}).winid)
3888  new | only
3889
3890  call delete('Xtestfile1')
3891  call delete('Xtestfile2')
3892endfunc
3893
3894" Test for parsing entries using visual screen column
3895func Test_viscol()
3896  enew
3897  call writefile(["Col1\tCol2\tCol3"], 'Xfile1')
3898  edit Xfile1
3899
3900  " Use byte offset for column number
3901  set efm&
3902  cexpr "Xfile1:1:5:XX\nXfile1:1:9:YY\nXfile1:1:20:ZZ"
3903  call assert_equal([5, 8], [col('.'), virtcol('.')])
3904  cnext
3905  call assert_equal([9, 12], [col('.'), virtcol('.')])
3906  cnext
3907  call assert_equal([14, 20], [col('.'), virtcol('.')])
3908
3909  " Use screen column offset for column number
3910  set efm=%f:%l:%v:%m
3911  cexpr "Xfile1:1:8:XX\nXfile1:1:12:YY\nXfile1:1:20:ZZ"
3912  call assert_equal([5, 8], [col('.'), virtcol('.')])
3913  cnext
3914  call assert_equal([9, 12], [col('.'), virtcol('.')])
3915  cnext
3916  call assert_equal([14, 20], [col('.'), virtcol('.')])
3917  cexpr "Xfile1:1:6:XX\nXfile1:1:15:YY\nXfile1:1:24:ZZ"
3918  call assert_equal([5, 8], [col('.'), virtcol('.')])
3919  cnext
3920  call assert_equal([10, 16], [col('.'), virtcol('.')])
3921  cnext
3922  call assert_equal([14, 20], [col('.'), virtcol('.')])
3923
3924  enew
3925  call writefile(["Col1\täü\töß\tCol4"], 'Xfile1')
3926
3927  " Use byte offset for column number
3928  set efm&
3929  cexpr "Xfile1:1:8:XX\nXfile1:1:11:YY\nXfile1:1:16:ZZ"
3930  call assert_equal([8, 10], [col('.'), virtcol('.')])
3931  cnext
3932  call assert_equal([11, 17], [col('.'), virtcol('.')])
3933  cnext
3934  call assert_equal([16, 25], [col('.'), virtcol('.')])
3935
3936  " Use screen column offset for column number
3937  set efm=%f:%l:%v:%m
3938  cexpr "Xfile1:1:10:XX\nXfile1:1:17:YY\nXfile1:1:25:ZZ"
3939  call assert_equal([8, 10], [col('.'), virtcol('.')])
3940  cnext
3941  call assert_equal([11, 17], [col('.'), virtcol('.')])
3942  cnext
3943  call assert_equal([16, 25], [col('.'), virtcol('.')])
3944
3945  enew | only
3946  set efm&
3947  call delete('Xfile1')
3948endfunc
3949
3950" Test for the quickfix window buffer
3951func Xqfbuf_test(cchar)
3952  call s:setup_commands(a:cchar)
3953
3954  " Quickfix buffer should be reused across closing and opening a quickfix
3955  " window
3956  Xexpr "F1:10:Line10"
3957  Xopen
3958  let qfbnum = bufnr('')
3959  Xclose
3960  " Even after the quickfix window is closed, the buffer should be loaded
3961  call assert_true(bufloaded(qfbnum))
3962  call assert_true(qfbnum, g:Xgetlist({'qfbufnr' : 0}).qfbufnr)
3963  Xopen
3964  " Buffer should be reused when opening the window again
3965  call assert_equal(qfbnum, bufnr(''))
3966  Xclose
3967
3968  if a:cchar == 'l'
3969    %bwipe
3970    " For a location list, when both the file window and the location list
3971    " window for the list are closed, then the buffer should be freed.
3972    new | only
3973    lexpr "F1:10:Line10"
3974    let wid = win_getid()
3975    lopen
3976    let qfbnum = bufnr('')
3977    call assert_match(qfbnum . ' %a-  "\[Location List]"', execute('ls'))
3978    close
3979    " When the location list window is closed, the buffer name should not
3980    " change to 'Quickfix List'
3981    call assert_match(qfbnum . 'u h-  "\[Location List]"', execute('ls!'))
3982    call assert_true(bufloaded(qfbnum))
3983
3984    " After deleting a location list buffer using ":bdelete", opening the
3985    " location list window should mark the buffer as a location list buffer.
3986    exe "bdelete " . qfbnum
3987    lopen
3988    call assert_equal("quickfix", &buftype)
3989    call assert_equal(1, getwininfo(win_getid(winnr()))[0].loclist)
3990    call assert_equal(wid, getloclist(0, {'filewinid' : 0}).filewinid)
3991    call assert_false(&swapfile)
3992    lclose
3993
3994    " When the location list is cleared for the window, the buffer should be
3995    " removed
3996    call setloclist(0, [], 'f')
3997    call assert_false(bufexists(qfbnum))
3998    call assert_equal(0, getloclist(0, {'qfbufnr' : 0}).qfbufnr)
3999
4000    " When the location list is freed with the location list window open, the
4001    " location list buffer should not be lost. It should be reused when the
4002    " location list is again populated.
4003    lexpr "F1:10:Line10"
4004    lopen
4005    let wid = win_getid()
4006    let qfbnum = bufnr('')
4007    wincmd p
4008    call setloclist(0, [], 'f')
4009    lexpr "F1:10:Line10"
4010    lopen
4011    call assert_equal(wid, win_getid())
4012    call assert_equal(qfbnum, bufnr(''))
4013    lclose
4014
4015    " When the window with the location list is closed, the buffer should be
4016    " removed
4017    new | only
4018    call assert_false(bufexists(qfbnum))
4019  endif
4020endfunc
4021
4022func Test_qfbuf()
4023  call Xqfbuf_test('c')
4024  call Xqfbuf_test('l')
4025endfunc
4026
4027" If there is an autocmd to use only one window, then opening the location
4028" list window used to crash Vim.
4029func Test_winonly_autocmd()
4030  call s:create_test_file('Xtest1')
4031  " Autocmd to show only one Vim window at a time
4032  autocmd WinEnter * only
4033  new
4034  " Load the location list
4035  lexpr "Xtest1:5:Line5\nXtest1:10:Line10\nXtest1:15:Line15"
4036  let loclistid = getloclist(0, {'id' : 0}).id
4037  " Open the location list window. Only this window will be shown and the file
4038  " window is closed.
4039  lopen
4040  call assert_equal(loclistid, getloclist(0, {'id' : 0}).id)
4041  " Jump to an entry in the location list and make sure that the cursor is
4042  " positioned correctly.
4043  ll 3
4044  call assert_equal(loclistid, getloclist(0, {'id' : 0}).id)
4045  call assert_equal('Xtest1', bufname(''))
4046  call assert_equal(15, line('.'))
4047  " Cleanup
4048  autocmd! WinEnter
4049  new | only
4050  call delete('Xtest1')
4051endfunc
4052
4053" Test to make sure that an empty quickfix buffer is not reused for loading
4054" a normal buffer.
4055func Test_empty_qfbuf()
4056  enew | only
4057  call writefile(["Test"], 'Xfile1')
4058  call setqflist([], 'f')
4059  copen | only
4060  let qfbuf = bufnr('')
4061  edit Xfile1
4062  call assert_notequal(qfbuf, bufnr(''))
4063  enew
4064  call delete('Xfile1')
4065endfunc
4066
4067" Test for the :cbelow, :cabove, :lbelow and :labove commands.
4068" And for the :cafter, :cbefore, :lafter and :lbefore commands.
4069func Xtest_below(cchar)
4070  call s:setup_commands(a:cchar)
4071
4072  " No quickfix/location list
4073  call assert_fails('Xbelow', 'E42:')
4074  call assert_fails('Xabove', 'E42:')
4075  call assert_fails('Xbefore', 'E42:')
4076  call assert_fails('Xafter', 'E42:')
4077
4078  " Empty quickfix/location list
4079  call g:Xsetlist([])
4080  call assert_fails('Xbelow', 'E42:')
4081  call assert_fails('Xabove', 'E42:')
4082  call assert_fails('Xbefore', 'E42:')
4083  call assert_fails('Xafter', 'E42:')
4084
4085  call s:create_test_file('X1')
4086  call s:create_test_file('X2')
4087  call s:create_test_file('X3')
4088  call s:create_test_file('X4')
4089
4090  " Invalid entries
4091  edit X1
4092  call g:Xsetlist(["E1", "E2"])
4093  call assert_fails('Xbelow', 'E42:')
4094  call assert_fails('Xabove', 'E42:')
4095  call assert_fails('3Xbelow', 'E42:')
4096  call assert_fails('4Xabove', 'E42:')
4097  call assert_fails('Xbefore', 'E42:')
4098  call assert_fails('Xafter', 'E42:')
4099  call assert_fails('3Xbefore', 'E42:')
4100  call assert_fails('4Xafter', 'E42:')
4101
4102  " Test the commands with various arguments
4103  Xexpr ["X1:5:3:L5", "X2:5:2:L5", "X2:10:3:L10", "X2:15:4:L15", "X3:3:5:L3"]
4104  edit +7 X2
4105  Xabove
4106  call assert_equal(['X2', 5], [bufname(''), line('.')])
4107  call assert_fails('Xabove', 'E553:')
4108  normal 7G
4109  Xbefore
4110  call assert_equal(['X2', 5, 2], [bufname(''), line('.'), col('.')])
4111  call assert_fails('Xbefore', 'E553:')
4112
4113  normal 2j
4114  Xbelow
4115  call assert_equal(['X2', 10], [bufname(''), line('.')])
4116  normal 7G
4117  Xafter
4118  call assert_equal(['X2', 10, 3], [bufname(''), line('.'), col('.')])
4119
4120  " Last error in this file
4121  Xbelow 99
4122  call assert_equal(['X2', 15], [bufname(''), line('.')])
4123  call assert_fails('Xbelow', 'E553:')
4124  normal gg
4125  Xafter 99
4126  call assert_equal(['X2', 15, 4], [bufname(''), line('.'), col('.')])
4127  call assert_fails('Xafter', 'E553:')
4128
4129  " First error in this file
4130  Xabove 99
4131  call assert_equal(['X2', 5], [bufname(''), line('.')])
4132  call assert_fails('Xabove', 'E553:')
4133  normal G
4134  Xbefore 99
4135  call assert_equal(['X2', 5, 2], [bufname(''), line('.'), col('.')])
4136  call assert_fails('Xbefore', 'E553:')
4137
4138  normal gg
4139  Xbelow 2
4140  call assert_equal(['X2', 10], [bufname(''), line('.')])
4141  normal gg
4142  Xafter 2
4143  call assert_equal(['X2', 10, 3], [bufname(''), line('.'), col('.')])
4144
4145  normal G
4146  Xabove 2
4147  call assert_equal(['X2', 10], [bufname(''), line('.')])
4148  normal G
4149  Xbefore 2
4150  call assert_equal(['X2', 10, 3], [bufname(''), line('.'), col('.')])
4151
4152  edit X4
4153  call assert_fails('Xabove', 'E42:')
4154  call assert_fails('Xbelow', 'E42:')
4155  call assert_fails('Xbefore', 'E42:')
4156  call assert_fails('Xafter', 'E42:')
4157  if a:cchar == 'l'
4158    " If a buffer has location list entries from some other window but not
4159    " from the current window, then the commands should fail.
4160    edit X1 | split | call setloclist(0, [], 'f')
4161    call assert_fails('Xabove', 'E776:')
4162    call assert_fails('Xbelow', 'E776:')
4163    call assert_fails('Xbefore', 'E776:')
4164    call assert_fails('Xafter', 'E776:')
4165    close
4166  endif
4167
4168  " Test for lines with multiple quickfix entries
4169  Xexpr ["X1:5:L5", "X2:5:1:L5_1", "X2:5:2:L5_2", "X2:5:3:L5_3",
4170	      \ "X2:10:1:L10_1", "X2:10:2:L10_2", "X2:10:3:L10_3",
4171	      \ "X2:15:1:L15_1", "X2:15:2:L15_2", "X2:15:3:L15_3", "X3:3:L3"]
4172  edit +1 X2
4173  Xbelow 2
4174  call assert_equal(['X2', 10, 1], [bufname(''), line('.'), col('.')])
4175  normal 1G
4176  Xafter 2
4177  call assert_equal(['X2', 5, 2], [bufname(''), line('.'), col('.')])
4178
4179  normal gg
4180  Xbelow 99
4181  call assert_equal(['X2', 15, 1], [bufname(''), line('.'), col('.')])
4182  normal gg
4183  Xafter 99
4184  call assert_equal(['X2', 15, 3], [bufname(''), line('.'), col('.')])
4185
4186  normal G
4187  Xabove 2
4188  call assert_equal(['X2', 10, 1], [bufname(''), line('.'), col('.')])
4189  normal G
4190  Xbefore 2
4191  call assert_equal(['X2', 15, 2], [bufname(''), line('.'), col('.')])
4192
4193  normal G
4194  Xabove 99
4195  call assert_equal(['X2', 5, 1], [bufname(''), line('.'), col('.')])
4196  normal G
4197  Xbefore 99
4198  call assert_equal(['X2', 5, 1], [bufname(''), line('.'), col('.')])
4199
4200  normal 10G
4201  Xabove
4202  call assert_equal(['X2', 5, 1], [bufname(''), line('.'), col('.')])
4203  normal 10G$
4204  2Xbefore
4205  call assert_equal(['X2', 10, 2], [bufname(''), line('.'), col('.')])
4206
4207  normal 10G
4208  Xbelow
4209  call assert_equal(['X2', 15, 1], [bufname(''), line('.'), col('.')])
4210  normal 9G
4211  5Xafter
4212  call assert_equal(['X2', 15, 2], [bufname(''), line('.'), col('.')])
4213
4214  " Invalid range
4215  if a:cchar == 'c'
4216    call assert_fails('-2cbelow', 'E16:')
4217    call assert_fails('-2cafter', 'E16:')
4218  else
4219    call assert_fails('-2lbelow', 'E16:')
4220    call assert_fails('-2lafter', 'E16:')
4221  endif
4222
4223  call delete('X1')
4224  call delete('X2')
4225  call delete('X3')
4226  call delete('X4')
4227endfunc
4228
4229func Test_cbelow()
4230  call Xtest_below('c')
4231  call Xtest_below('l')
4232endfunc
4233
4234func Test_quickfix_count()
4235  let commands = [
4236	\ 'cNext',
4237	\ 'cNfile',
4238	\ 'cabove',
4239	\ 'cbelow',
4240	\ 'cfirst',
4241	\ 'clast',
4242	\ 'cnewer',
4243	\ 'cnext',
4244	\ 'cnfile',
4245	\ 'colder',
4246	\ 'cprevious',
4247	\ 'crewind',
4248	\
4249	\ 'lNext',
4250	\ 'lNfile',
4251	\ 'labove',
4252	\ 'lbelow',
4253	\ 'lfirst',
4254	\ 'llast',
4255	\ 'lnewer',
4256	\ 'lnext',
4257	\ 'lnfile',
4258	\ 'lolder',
4259	\ 'lprevious',
4260	\ 'lrewind',
4261	\ ]
4262  for cmd in commands
4263    call assert_fails('-1' .. cmd, 'E16:')
4264    call assert_fails('.' .. cmd, 'E16:')
4265    call assert_fails('%' .. cmd, 'E16:')
4266    call assert_fails('$' .. cmd, 'E16:')
4267  endfor
4268endfunc
4269