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