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_setqflist_user_sets_buftype()
1632  call setqflist([{'text': 'foo'}, {'text': 'bar'}])
1633  set buftype=quickfix
1634  call setqflist([], 'a')
1635  enew
1636endfunc
1637
1638func Test_quickfix_set_list_with_act()
1639  call XquickfixSetListWithAct('c')
1640  call XquickfixSetListWithAct('l')
1641endfunc
1642
1643func XLongLinesTests(cchar)
1644  let l = g:Xgetlist()
1645
1646  call assert_equal(4, len(l))
1647  call assert_equal(1, l[0].lnum)
1648  call assert_equal(1, l[0].col)
1649  call assert_equal(1975, len(l[0].text))
1650  call assert_equal(2, l[1].lnum)
1651  call assert_equal(1, l[1].col)
1652  call assert_equal(4070, len(l[1].text))
1653  call assert_equal(3, l[2].lnum)
1654  call assert_equal(1, l[2].col)
1655  call assert_equal(4070, len(l[2].text))
1656  call assert_equal(4, l[3].lnum)
1657  call assert_equal(1, l[3].col)
1658  call assert_equal(10, len(l[3].text))
1659
1660  call g:Xsetlist([], 'r')
1661endfunc
1662
1663func s:long_lines_tests(cchar)
1664  call s:setup_commands(a:cchar)
1665
1666  let testfile = 'samples/quickfix.txt'
1667
1668  " file
1669  exe 'Xgetfile' testfile
1670  call XLongLinesTests(a:cchar)
1671
1672  " list
1673  Xexpr readfile(testfile)
1674  call XLongLinesTests(a:cchar)
1675
1676  " string
1677  Xexpr join(readfile(testfile), "\n")
1678  call XLongLinesTests(a:cchar)
1679
1680  " buffer
1681  exe 'edit' testfile
1682  exe 'Xbuffer' bufnr('%')
1683  call XLongLinesTests(a:cchar)
1684endfunc
1685
1686func Test_long_lines()
1687  call s:long_lines_tests('c')
1688  call s:long_lines_tests('l')
1689endfunc
1690
1691func s:create_test_file(filename)
1692  let l = []
1693  for i in range(1, 20)
1694      call add(l, 'Line' . i)
1695  endfor
1696  call writefile(l, a:filename)
1697endfunc
1698
1699func Test_switchbuf()
1700  CheckNotBSD
1701  call s:create_test_file('Xqftestfile1')
1702  call s:create_test_file('Xqftestfile2')
1703  call s:create_test_file('Xqftestfile3')
1704
1705  new | only
1706  edit Xqftestfile1
1707  let file1_winid = win_getid()
1708  new Xqftestfile2
1709  let file2_winid = win_getid()
1710  cgetexpr ['Xqftestfile1:5:Line5',
1711		\ 'Xqftestfile1:6:Line6',
1712		\ 'Xqftestfile2:10:Line10',
1713		\ 'Xqftestfile2:11:Line11',
1714		\ 'Xqftestfile3:15:Line15',
1715		\ 'Xqftestfile3:16:Line16']
1716
1717  new
1718  let winid = win_getid()
1719  cfirst | cnext
1720  call assert_equal(winid, win_getid())
1721  2cnext
1722  call assert_equal(winid, win_getid())
1723  2cnext
1724  call assert_equal(winid, win_getid())
1725
1726  " Test for 'switchbuf' set to search for files in windows in the current
1727  " tabpage and jump to an existing window (if present)
1728  set switchbuf=useopen
1729  enew
1730  cfirst | cnext
1731  call assert_equal(file1_winid, win_getid())
1732  2cnext
1733  call assert_equal(file2_winid, win_getid())
1734  2cnext
1735  call assert_equal(file2_winid, win_getid())
1736
1737  " Test for 'switchbuf' set to search for files in tabpages and jump to an
1738  " existing tabpage (if present)
1739  enew | only
1740  set switchbuf=usetab
1741  tabedit Xqftestfile1
1742  tabedit Xqftestfile2
1743  tabedit Xqftestfile3
1744  tabfirst
1745  cfirst | cnext
1746  call assert_equal(2, tabpagenr())
1747  2cnext
1748  call assert_equal(3, tabpagenr())
1749  6cnext
1750  call assert_equal(4, tabpagenr())
1751  2cpfile
1752  call assert_equal(2, tabpagenr())
1753  2cnfile
1754  call assert_equal(4, tabpagenr())
1755  tabfirst | tabonly | enew
1756
1757  " Test for 'switchbuf' set to open a new window for every file
1758  set switchbuf=split
1759  cfirst | cnext
1760  call assert_equal(1, winnr('$'))
1761  cnext | cnext
1762  call assert_equal(2, winnr('$'))
1763  cnext | cnext
1764  call assert_equal(3, winnr('$'))
1765
1766  " Test for 'switchbuf' set to open a new tabpage for every file
1767  set switchbuf=newtab
1768  enew | only
1769  cfirst | cnext
1770  call assert_equal(1, tabpagenr('$'))
1771  cnext | cnext
1772  call assert_equal(2, tabpagenr('$'))
1773  cnext | cnext
1774  call assert_equal(3, tabpagenr('$'))
1775  tabfirst | enew | tabonly | only
1776
1777  set switchbuf=uselast
1778  split
1779  let last_winid = win_getid()
1780  copen
1781  exe "normal 1G\<CR>"
1782  call assert_equal(last_winid, win_getid())
1783  enew | only
1784
1785  " With an empty 'switchbuf', jumping to a quickfix entry should open the
1786  " file in an existing window (if present)
1787  set switchbuf=
1788  edit Xqftestfile1
1789  let file1_winid = win_getid()
1790  new Xqftestfile2
1791  let file2_winid = win_getid()
1792  copen
1793  exe "normal 1G\<CR>"
1794  call assert_equal(file1_winid, win_getid())
1795  copen
1796  exe "normal 3G\<CR>"
1797  call assert_equal(file2_winid, win_getid())
1798  copen | only
1799  exe "normal 5G\<CR>"
1800  call assert_equal(2, winnr('$'))
1801  call assert_equal(1, bufwinnr('Xqftestfile3'))
1802
1803  " If only quickfix window is open in the current tabpage, jumping to an
1804  " entry with 'switchbuf' set to 'usetab' should search in other tabpages.
1805  enew | only
1806  set switchbuf=usetab
1807  tabedit Xqftestfile1
1808  tabedit Xqftestfile2
1809  tabedit Xqftestfile3
1810  tabfirst
1811  copen | only
1812  clast
1813  call assert_equal(4, tabpagenr())
1814  tabfirst | tabonly | enew | only
1815
1816  " Jumping to a file that is not present in any of the tabpages and the
1817  " current tabpage doesn't have any usable windows, should open it in a new
1818  " window in the current tabpage.
1819  copen | only
1820  cfirst
1821  call assert_equal(1, tabpagenr())
1822  call assert_equal('Xqftestfile1', bufname(''))
1823
1824  " If opening a file changes 'switchbuf', then the new value should be
1825  " retained.
1826  call writefile(["vim: switchbuf=split"], 'Xqftestfile1')
1827  enew | only
1828  set switchbuf&vim
1829  cexpr "Xqftestfile1:1:10"
1830  call assert_equal('split', &switchbuf)
1831  call writefile(["vim: switchbuf=usetab"], 'Xqftestfile1')
1832  enew | only
1833  set switchbuf=useopen
1834  cexpr "Xqftestfile1:1:10"
1835  call assert_equal('usetab', &switchbuf)
1836  call writefile(["vim: switchbuf&vim"], 'Xqftestfile1')
1837  enew | only
1838  set switchbuf=useopen
1839  cexpr "Xqftestfile1:1:10"
1840  call assert_equal('', &switchbuf)
1841
1842  call delete('Xqftestfile1')
1843  call delete('Xqftestfile2')
1844  call delete('Xqftestfile3')
1845  set switchbuf&vim
1846
1847  enew | only
1848endfunc
1849
1850func Xadjust_qflnum(cchar)
1851  call s:setup_commands(a:cchar)
1852
1853  enew | only
1854
1855  let fname = 'Xqftestfile' . a:cchar
1856  call s:create_test_file(fname)
1857  exe 'edit ' . fname
1858
1859  Xgetexpr [fname . ':5:Line5',
1860	      \ fname . ':10:Line10',
1861	      \ fname . ':15:Line15',
1862	      \ fname . ':20:Line20']
1863
1864  6,14delete
1865  call append(6, ['Buffer', 'Window'])
1866
1867  let l = g:Xgetlist()
1868  call assert_equal(5, l[0].lnum)
1869  call assert_equal(6, l[2].lnum)
1870  call assert_equal(13, l[3].lnum)
1871
1872  " If a file doesn't have any quickfix entries, then deleting lines in the
1873  " file should not update the quickfix list
1874  call g:Xsetlist([], 'f')
1875  1,2delete
1876  call assert_equal([], g:Xgetlist())
1877
1878  enew!
1879  call delete(fname)
1880endfunc
1881
1882func Test_adjust_lnum()
1883  call setloclist(0, [])
1884  call Xadjust_qflnum('c')
1885  call setqflist([])
1886  call Xadjust_qflnum('l')
1887endfunc
1888
1889" Tests for the :grep/:lgrep and :grepadd/:lgrepadd commands
1890func s:test_xgrep(cchar)
1891  call s:setup_commands(a:cchar)
1892
1893  " The following lines are used for the grep test. Don't remove.
1894  " Grep_Test_Text: Match 1
1895  " Grep_Test_Text: Match 2
1896  " GrepAdd_Test_Text: Match 1
1897  " GrepAdd_Test_Text: Match 2
1898  enew! | only
1899  set makeef&vim
1900  silent Xgrep Grep_Test_Text: test_quickfix.vim
1901  call assert_true(len(g:Xgetlist()) == 5)
1902  Xopen
1903  call assert_true(w:quickfix_title =~ '^:grep')
1904  Xclose
1905  enew
1906  set makeef=Temp_File_##
1907  silent Xgrepadd GrepAdd_Test_Text: test_quickfix.vim
1908  call assert_true(len(g:Xgetlist()) == 9)
1909
1910  " Try with 'grepprg' set to 'internal'
1911  set grepprg=internal
1912  silent Xgrep Grep_Test_Text: test_quickfix.vim
1913  silent Xgrepadd GrepAdd_Test_Text: test_quickfix.vim
1914  call assert_true(len(g:Xgetlist()) == 9)
1915  set grepprg&vim
1916
1917  call writefile(['Vim'], 'XtestTempFile')
1918  set makeef=XtestTempFile
1919  silent Xgrep Grep_Test_Text: test_quickfix.vim
1920  call assert_equal(5, len(g:Xgetlist()))
1921  call assert_false(filereadable('XtestTempFile'))
1922  set makeef&vim
1923endfunc
1924
1925func Test_grep()
1926  if !has('unix')
1927    " The grepprg may not be set on non-Unix systems
1928    return
1929  endif
1930
1931  call s:test_xgrep('c')
1932  call s:test_xgrep('l')
1933endfunc
1934
1935func Test_two_windows()
1936  " Use one 'errorformat' for two windows.  Add an expression to each of them,
1937  " make sure they each keep their own state.
1938  set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f'
1939  call mkdir('Xone/a', 'p')
1940  call mkdir('Xtwo/a', 'p')
1941  let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7']
1942  call writefile(lines, 'Xone/a/one.txt')
1943  call writefile(lines, 'Xtwo/a/two.txt')
1944
1945  new one
1946  let one_id = win_getid()
1947  lexpr ""
1948  new two
1949  let two_id = win_getid()
1950  lexpr ""
1951
1952  laddexpr "Entering dir 'Xtwo/a'"
1953  call win_gotoid(one_id)
1954  laddexpr "Entering dir 'Xone/a'"
1955  call win_gotoid(two_id)
1956  laddexpr 'two.txt:5:two two two'
1957  call win_gotoid(one_id)
1958  laddexpr 'one.txt:3:one one one'
1959
1960  let loc_one = getloclist(one_id)
1961  call assert_equal('Xone/a/one.txt', bufname(loc_one[1].bufnr))
1962  call assert_equal(3, loc_one[1].lnum)
1963
1964  let loc_two = getloclist(two_id)
1965  call assert_equal('Xtwo/a/two.txt', bufname(loc_two[1].bufnr))
1966  call assert_equal(5, loc_two[1].lnum)
1967
1968  call win_gotoid(one_id)
1969  bwipe!
1970  call win_gotoid(two_id)
1971  bwipe!
1972  call delete('Xone', 'rf')
1973  call delete('Xtwo', 'rf')
1974endfunc
1975
1976func XbottomTests(cchar)
1977  call s:setup_commands(a:cchar)
1978
1979  " Calling lbottom without any errors should fail
1980  if a:cchar == 'l'
1981      call assert_fails('lbottom', 'E776:')
1982  endif
1983
1984  call g:Xsetlist([{'filename': 'foo', 'lnum': 42}])
1985  Xopen
1986  let wid = win_getid()
1987  call assert_equal(1, line('.'))
1988  wincmd w
1989  call g:Xsetlist([{'filename': 'var', 'lnum': 24}], 'a')
1990  Xbottom
1991  call win_gotoid(wid)
1992  call assert_equal(2, line('.'))
1993  Xclose
1994endfunc
1995
1996" Tests for the :cbottom and :lbottom commands
1997func Test_cbottom()
1998  call XbottomTests('c')
1999  call XbottomTests('l')
2000endfunc
2001
2002func HistoryTest(cchar)
2003  call s:setup_commands(a:cchar)
2004
2005  " clear all lists after the first one, then replace the first one.
2006  call g:Xsetlist([])
2007  call assert_fails('Xolder 99', 'E380:')
2008  let entry = {'filename': 'foo', 'lnum': 42}
2009  call g:Xsetlist([entry], 'r')
2010  call g:Xsetlist([entry, entry])
2011  call g:Xsetlist([entry, entry, entry])
2012  let res = split(execute(a:cchar . 'hist'), "\n")
2013  call assert_equal(3, len(res))
2014  let common = 'errors     :set' . (a:cchar == 'c' ? 'qf' : 'loc') . 'list()'
2015  call assert_equal('  error list 1 of 3; 1 ' . common, res[0])
2016  call assert_equal('  error list 2 of 3; 2 ' . common, res[1])
2017  call assert_equal('> error list 3 of 3; 3 ' . common, res[2])
2018
2019  " Test for changing the quickfix lists
2020  call assert_equal(3, g:Xgetlist({'nr' : 0}).nr)
2021  exe '1' . a:cchar . 'hist'
2022  call assert_equal(1, g:Xgetlist({'nr' : 0}).nr)
2023  exe '3' . a:cchar . 'hist'
2024  call assert_equal(3, g:Xgetlist({'nr' : 0}).nr)
2025  call assert_fails('-2' . a:cchar . 'hist', 'E16:')
2026  call assert_fails('4' . a:cchar . 'hist', 'E16:')
2027
2028  call g:Xsetlist([], 'f')
2029  let l = split(execute(a:cchar . 'hist'), "\n")
2030  call assert_equal('No entries', l[0])
2031  if a:cchar == 'c'
2032    call assert_fails('4chist', 'E16:')
2033  else
2034    call assert_fails('4lhist', 'E776:')
2035  endif
2036
2037  " An empty list should still show the stack history
2038  call g:Xsetlist([])
2039  let res = split(execute(a:cchar . 'hist'), "\n")
2040  call assert_equal('> error list 1 of 1; 0 ' . common, res[0])
2041
2042  call g:Xsetlist([], 'f')
2043endfunc
2044
2045func Test_history()
2046  call HistoryTest('c')
2047  call HistoryTest('l')
2048endfunc
2049
2050func Test_duplicate_buf()
2051  " make sure we can get the highest buffer number
2052  edit DoesNotExist
2053  edit DoesNotExist2
2054  let last_buffer = bufnr("$")
2055
2056  " make sure only one buffer is created
2057  call writefile(['this one', 'that one'], 'Xgrepthis')
2058  vimgrep one Xgrepthis
2059  vimgrep one Xgrepthis
2060  call assert_equal(last_buffer + 1, bufnr("$"))
2061
2062  call delete('Xgrepthis')
2063endfunc
2064
2065" Quickfix/Location list set/get properties tests
2066func Xproperty_tests(cchar)
2067    call s:setup_commands(a:cchar)
2068
2069    " Error cases
2070    call assert_fails('call g:Xgetlist(99)', 'E715:')
2071    call assert_fails('call g:Xsetlist(99)', 'E714:')
2072    call assert_fails('call g:Xsetlist([], "a", [])', 'E715:')
2073
2074    " Set and get the title
2075    call g:Xsetlist([])
2076    Xopen
2077    wincmd p
2078    call g:Xsetlist([{'filename':'foo', 'lnum':27}])
2079    let s = g:Xsetlist([], 'a', {'title' : 'Sample'})
2080    call assert_equal(0, s)
2081    let d = g:Xgetlist({"title":1})
2082    call assert_equal('Sample', d.title)
2083    " Try setting title to a non-string value
2084    call assert_equal(-1, g:Xsetlist([], 'a', {'title' : ['Test']}))
2085    call assert_equal('Sample', g:Xgetlist({"title":1}).title)
2086
2087    Xopen
2088    call assert_equal('Sample', w:quickfix_title)
2089    Xclose
2090
2091    " Tests for action argument
2092    silent! Xolder 999
2093    let qfnr = g:Xgetlist({'all':1}).nr
2094    call g:Xsetlist([], 'r', {'title' : 'N1'})
2095    call assert_equal('N1', g:Xgetlist({'all':1}).title)
2096    call g:Xsetlist([], ' ', {'title' : 'N2'})
2097    call assert_equal(qfnr + 1, g:Xgetlist({'all':1}).nr)
2098
2099    let res = g:Xgetlist({'nr': 0})
2100    call assert_equal(qfnr + 1, res.nr)
2101    call assert_equal(['nr'], keys(res))
2102
2103    call g:Xsetlist([], ' ', {'title' : 'N3'})
2104    call assert_equal('N2', g:Xgetlist({'nr':2, 'title':1}).title)
2105
2106    " Changing the title of an earlier quickfix list
2107    call g:Xsetlist([], 'r', {'title' : 'NewTitle', 'nr' : 2})
2108    call assert_equal('NewTitle', g:Xgetlist({'nr':2, 'title':1}).title)
2109
2110    " Changing the title of an invalid quickfix list
2111    call assert_equal(-1, g:Xsetlist([], ' ',
2112		\ {'title' : 'SomeTitle', 'nr' : 99}))
2113    call assert_equal(-1, g:Xsetlist([], ' ',
2114		\ {'title' : 'SomeTitle', 'nr' : 'abc'}))
2115
2116    if a:cchar == 'c'
2117	copen
2118	call assert_equal({'winid':win_getid()}, getqflist({'winid':1}))
2119	cclose
2120    endif
2121
2122    " Invalid arguments
2123    call assert_fails('call g:Xgetlist([])', 'E715')
2124    call assert_fails('call g:Xsetlist([], "a", [])', 'E715')
2125    let s = g:Xsetlist([], 'a', {'abc':1})
2126    call assert_equal(-1, s)
2127
2128    call assert_equal({}, g:Xgetlist({'abc':1}))
2129    call assert_equal('', g:Xgetlist({'nr':99, 'title':1}).title)
2130    call assert_equal('', g:Xgetlist({'nr':[], 'title':1}).title)
2131
2132    if a:cchar == 'l'
2133	call assert_equal({}, getloclist(99, {'title': 1}))
2134    endif
2135
2136    " Context related tests
2137    let s = g:Xsetlist([], 'a', {'context':[1,2,3]})
2138    call assert_equal(0, s)
2139    call test_garbagecollect_now()
2140    let d = g:Xgetlist({'context':1})
2141    call assert_equal([1,2,3], d.context)
2142    call g:Xsetlist([], 'a', {'context':{'color':'green'}})
2143    let d = g:Xgetlist({'context':1})
2144    call assert_equal({'color':'green'}, d.context)
2145    call g:Xsetlist([], 'a', {'context':"Context info"})
2146    let d = g:Xgetlist({'context':1})
2147    call assert_equal("Context info", d.context)
2148    call g:Xsetlist([], 'a', {'context':246})
2149    let d = g:Xgetlist({'context':1})
2150    call assert_equal(246, d.context)
2151    if a:cchar == 'l'
2152	" Test for copying context across two different location lists
2153	new | only
2154	let w1_id = win_getid()
2155	let l = [1]
2156	call setloclist(0, [], 'a', {'context':l})
2157	new
2158	let w2_id = win_getid()
2159	call add(l, 2)
2160	call assert_equal([1, 2], getloclist(w1_id, {'context':1}).context)
2161	call assert_equal([1, 2], getloclist(w2_id, {'context':1}).context)
2162	unlet! l
2163	call assert_equal([1, 2], getloclist(w2_id, {'context':1}).context)
2164	only
2165	call setloclist(0, [], 'f')
2166	call assert_equal('', getloclist(0, {'context':1}).context)
2167    endif
2168
2169    " Test for changing the context of previous quickfix lists
2170    call g:Xsetlist([], 'f')
2171    Xexpr "One"
2172    Xexpr "Two"
2173    Xexpr "Three"
2174    call g:Xsetlist([], 'r', {'context' : [1], 'nr' : 1})
2175    call g:Xsetlist([], 'a', {'context' : [2], 'nr' : 2})
2176    " Also, check for setting the context using quickfix list number zero.
2177    call g:Xsetlist([], 'r', {'context' : [3], 'nr' : 0})
2178    call test_garbagecollect_now()
2179    let l = g:Xgetlist({'nr' : 1, 'context' : 1})
2180    call assert_equal([1], l.context)
2181    let l = g:Xgetlist({'nr' : 2, 'context' : 1})
2182    call assert_equal([2], l.context)
2183    let l = g:Xgetlist({'nr' : 3, 'context' : 1})
2184    call assert_equal([3], l.context)
2185
2186    " Test for changing the context through reference and for garbage
2187    " collection of quickfix context
2188    let l = ["red"]
2189    call g:Xsetlist([], ' ', {'context' : l})
2190    call add(l, "blue")
2191    let x = g:Xgetlist({'context' : 1})
2192    call add(x.context, "green")
2193    call assert_equal(["red", "blue", "green"], l)
2194    call assert_equal(["red", "blue", "green"], x.context)
2195    unlet l
2196    call test_garbagecollect_now()
2197    let m = g:Xgetlist({'context' : 1})
2198    call assert_equal(["red", "blue", "green"], m.context)
2199
2200    " Test for setting/getting items
2201    Xexpr ""
2202    let qfprev = g:Xgetlist({'nr':0})
2203    let s = g:Xsetlist([], ' ', {'title':'Green',
2204		\ 'items' : [{'filename':'F1', 'lnum':10}]})
2205    call assert_equal(0, s)
2206    let qfcur = g:Xgetlist({'nr':0})
2207    call assert_true(qfcur.nr == qfprev.nr + 1)
2208    let l = g:Xgetlist({'items':1})
2209    call assert_equal('F1', bufname(l.items[0].bufnr))
2210    call assert_equal(10, l.items[0].lnum)
2211    call g:Xsetlist([], 'a', {'items' : [{'filename':'F2', 'lnum':20},
2212		\  {'filename':'F2', 'lnum':30}]})
2213    let l = g:Xgetlist({'items':1})
2214    call assert_equal('F2', bufname(l.items[2].bufnr))
2215    call assert_equal(30, l.items[2].lnum)
2216    call g:Xsetlist([], 'r', {'items' : [{'filename':'F3', 'lnum':40}]})
2217    let l = g:Xgetlist({'items':1})
2218    call assert_equal('F3', bufname(l.items[0].bufnr))
2219    call assert_equal(40, l.items[0].lnum)
2220    call g:Xsetlist([], 'r', {'items' : []})
2221    let l = g:Xgetlist({'items':1})
2222    call assert_equal(0, len(l.items))
2223
2224    call g:Xsetlist([], 'r', {'title' : 'TestTitle'})
2225    call g:Xsetlist([], 'r', {'items' : [{'filename' : 'F1', 'lnum' : 10, 'text' : 'L10'}]})
2226    call g:Xsetlist([], 'r', {'items' : [{'filename' : 'F1', 'lnum' : 10, 'text' : 'L10'}]})
2227    call assert_equal('TestTitle', g:Xgetlist({'title' : 1}).title)
2228
2229    " Test for getting id of window associated with a location list window
2230    if a:cchar == 'l'
2231      only
2232      call assert_equal(0, g:Xgetlist({'all' : 1}).filewinid)
2233      let wid = win_getid()
2234      Xopen
2235      call assert_equal(wid, g:Xgetlist({'filewinid' : 1}).filewinid)
2236      wincmd w
2237      call assert_equal(0, g:Xgetlist({'filewinid' : 1}).filewinid)
2238      only
2239    endif
2240
2241    " The following used to crash Vim with address sanitizer
2242    call g:Xsetlist([], 'f')
2243    call g:Xsetlist([], 'a', {'items' : [{'filename':'F1', 'lnum':10}]})
2244    call assert_equal(10, g:Xgetlist({'items':1}).items[0].lnum)
2245
2246    " Try setting the items using a string
2247    call assert_equal(-1, g:Xsetlist([], ' ', {'items' : 'Test'}))
2248
2249    " Save and restore the quickfix stack
2250    call g:Xsetlist([], 'f')
2251    call assert_equal(0, g:Xgetlist({'nr':'$'}).nr)
2252    Xexpr "File1:10:Line1"
2253    Xexpr "File2:20:Line2"
2254    Xexpr "File3:30:Line3"
2255    let last_qf = g:Xgetlist({'nr':'$'}).nr
2256    call assert_equal(3, last_qf)
2257    let qstack = []
2258    for i in range(1, last_qf)
2259	let qstack = add(qstack, g:Xgetlist({'nr':i, 'all':1}))
2260    endfor
2261    call g:Xsetlist([], 'f')
2262    for i in range(len(qstack))
2263	call g:Xsetlist([], ' ', qstack[i])
2264    endfor
2265    call assert_equal(3, g:Xgetlist({'nr':'$'}).nr)
2266    call assert_equal(10, g:Xgetlist({'nr':1, 'items':1}).items[0].lnum)
2267    call assert_equal(20, g:Xgetlist({'nr':2, 'items':1}).items[0].lnum)
2268    call assert_equal(30, g:Xgetlist({'nr':3, 'items':1}).items[0].lnum)
2269    call g:Xsetlist([], 'f')
2270
2271    " Swap two quickfix lists
2272    Xexpr "File1:10:Line10"
2273    Xexpr "File2:20:Line20"
2274    Xexpr "File3:30:Line30"
2275    call g:Xsetlist([], 'r', {'nr':1,'title':'Colors','context':['Colors']})
2276    call g:Xsetlist([], 'r', {'nr':2,'title':'Fruits','context':['Fruits']})
2277    let l1=g:Xgetlist({'nr':1,'all':1})
2278    let l2=g:Xgetlist({'nr':2,'all':1})
2279    let save_id = l1.id
2280    let l1.id=l2.id
2281    let l2.id=save_id
2282    call g:Xsetlist([], 'r', l1)
2283    call g:Xsetlist([], 'r', l2)
2284    let newl1=g:Xgetlist({'nr':1,'all':1})
2285    let newl2=g:Xgetlist({'nr':2,'all':1})
2286    call assert_equal('Fruits', newl1.title)
2287    call assert_equal(['Fruits'], newl1.context)
2288    call assert_equal('Line20', newl1.items[0].text)
2289    call assert_equal('Colors', newl2.title)
2290    call assert_equal(['Colors'], newl2.context)
2291    call assert_equal('Line10', newl2.items[0].text)
2292    call g:Xsetlist([], 'f')
2293endfunc
2294
2295func Test_qf_property()
2296    call Xproperty_tests('c')
2297    call Xproperty_tests('l')
2298endfunc
2299
2300" Test for setting the current index in the location/quickfix list
2301func Xtest_setqfidx(cchar)
2302  call s:setup_commands(a:cchar)
2303
2304  Xgetexpr "F1:10:1:Line1\nF2:20:2:Line2\nF3:30:3:Line3"
2305  Xgetexpr "F4:10:1:Line1\nF5:20:2:Line2\nF6:30:3:Line3"
2306  Xgetexpr "F7:10:1:Line1\nF8:20:2:Line2\nF9:30:3:Line3"
2307
2308  call g:Xsetlist([], 'a', {'nr' : 3, 'idx' : 2})
2309  call g:Xsetlist([], 'a', {'nr' : 2, 'idx' : 2})
2310  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 3})
2311  Xolder 2
2312  Xopen
2313  call assert_equal(3, line('.'))
2314  Xnewer
2315  call assert_equal(2, line('.'))
2316  Xnewer
2317  call assert_equal(2, line('.'))
2318  " Update the current index with the quickfix window open
2319  wincmd w
2320  call g:Xsetlist([], 'a', {'nr' : 3, 'idx' : 3})
2321  Xopen
2322  call assert_equal(3, line('.'))
2323  Xclose
2324
2325  " Set the current index to the last entry
2326  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : '$'})
2327  call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx)
2328  " A large value should set the index to the last index
2329  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 1})
2330  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 999})
2331  call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx)
2332  " Invalid index values
2333  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : -1})
2334  call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx)
2335  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 0})
2336  call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx)
2337  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 'xx'})
2338  call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx)
2339  call assert_fails("call g:Xsetlist([], 'a', {'nr':1, 'idx':[]})", 'E745:')
2340
2341  call g:Xsetlist([], 'f')
2342  new | only
2343endfunc
2344
2345func Test_setqfidx()
2346  call Xtest_setqfidx('c')
2347  call Xtest_setqfidx('l')
2348endfunc
2349
2350" Tests for the QuickFixCmdPre/QuickFixCmdPost autocommands
2351func QfAutoCmdHandler(loc, cmd)
2352  call add(g:acmds, a:loc . a:cmd)
2353endfunc
2354
2355func Test_Autocmd()
2356  autocmd QuickFixCmdPre * call QfAutoCmdHandler('pre', expand('<amatch>'))
2357  autocmd QuickFixCmdPost * call QfAutoCmdHandler('post', expand('<amatch>'))
2358
2359  let g:acmds = []
2360  cexpr "F1:10:Line 10"
2361  caddexpr "F1:20:Line 20"
2362  cgetexpr "F1:30:Line 30"
2363  cexpr ""
2364  caddexpr ""
2365  cgetexpr ""
2366  silent! cexpr non_existing_func()
2367  silent! caddexpr non_existing_func()
2368  silent! cgetexpr non_existing_func()
2369  let l = ['precexpr',
2370	      \ 'postcexpr',
2371	      \ 'precaddexpr',
2372	      \ 'postcaddexpr',
2373	      \ 'precgetexpr',
2374	      \ 'postcgetexpr',
2375	      \ 'precexpr',
2376	      \ 'postcexpr',
2377	      \ 'precaddexpr',
2378	      \ 'postcaddexpr',
2379	      \ 'precgetexpr',
2380	      \ 'postcgetexpr',
2381	      \ 'precexpr',
2382	      \ 'precaddexpr',
2383	      \ 'precgetexpr']
2384  call assert_equal(l, g:acmds)
2385
2386  let g:acmds = []
2387  enew! | call append(0, "F2:10:Line 10")
2388  cbuffer!
2389  enew! | call append(0, "F2:20:Line 20")
2390  cgetbuffer
2391  enew! | call append(0, "F2:30:Line 30")
2392  caddbuffer
2393  new
2394  let bnum = bufnr('%')
2395  bunload
2396  exe 'silent! cbuffer! ' . bnum
2397  exe 'silent! cgetbuffer ' . bnum
2398  exe 'silent! caddbuffer ' . bnum
2399  enew!
2400  let l = ['precbuffer',
2401	      \ 'postcbuffer',
2402	      \ 'precgetbuffer',
2403	      \ 'postcgetbuffer',
2404	      \ 'precaddbuffer',
2405	      \ 'postcaddbuffer',
2406	      \ 'precbuffer',
2407	      \ 'precgetbuffer',
2408	      \ 'precaddbuffer']
2409  call assert_equal(l, g:acmds)
2410
2411  call writefile(['Xtest:1:Line1'], 'Xtest')
2412  call writefile([], 'Xempty')
2413  let g:acmds = []
2414  cfile Xtest
2415  caddfile Xtest
2416  cgetfile Xtest
2417  cfile Xempty
2418  caddfile Xempty
2419  cgetfile Xempty
2420  silent! cfile do_not_exist
2421  silent! caddfile do_not_exist
2422  silent! cgetfile do_not_exist
2423  let l = ['precfile',
2424	      \ 'postcfile',
2425	      \ 'precaddfile',
2426	      \ 'postcaddfile',
2427	      \ 'precgetfile',
2428	      \ 'postcgetfile',
2429	      \ 'precfile',
2430	      \ 'postcfile',
2431	      \ 'precaddfile',
2432	      \ 'postcaddfile',
2433	      \ 'precgetfile',
2434	      \ 'postcgetfile',
2435	      \ 'precfile',
2436	      \ 'postcfile',
2437	      \ 'precaddfile',
2438	      \ 'postcaddfile',
2439	      \ 'precgetfile',
2440	      \ 'postcgetfile']
2441  call assert_equal(l, g:acmds)
2442
2443  let g:acmds = []
2444  helpgrep quickfix
2445  silent! helpgrep non_existing_help_topic
2446  vimgrep test Xtest
2447  vimgrepadd test Xtest
2448  silent! vimgrep non_existing_test Xtest
2449  silent! vimgrepadd non_existing_test Xtest
2450  set makeprg=
2451  silent! make
2452  set makeprg&
2453  let l = ['prehelpgrep',
2454	      \ 'posthelpgrep',
2455	      \ 'prehelpgrep',
2456	      \ 'posthelpgrep',
2457	      \ 'previmgrep',
2458	      \ 'postvimgrep',
2459	      \ 'previmgrepadd',
2460	      \ 'postvimgrepadd',
2461	      \ 'previmgrep',
2462	      \ 'postvimgrep',
2463	      \ 'previmgrepadd',
2464	      \ 'postvimgrepadd',
2465	      \ 'premake',
2466	      \ 'postmake']
2467  call assert_equal(l, g:acmds)
2468
2469  if has('unix')
2470    " Run this test only on Unix-like systems. The grepprg may not be set on
2471    " non-Unix systems.
2472    " The following lines are used for the grep test. Don't remove.
2473    " Grep_Autocmd_Text: Match 1
2474    " GrepAdd_Autocmd_Text: Match 2
2475    let g:acmds = []
2476    silent grep Grep_Autocmd_Text test_quickfix.vim
2477    silent grepadd GrepAdd_Autocmd_Text test_quickfix.vim
2478    silent grep abc123def Xtest
2479    silent grepadd abc123def Xtest
2480    set grepprg=internal
2481    silent grep Grep_Autocmd_Text test_quickfix.vim
2482    silent grepadd GrepAdd_Autocmd_Text test_quickfix.vim
2483    silent lgrep Grep_Autocmd_Text test_quickfix.vim
2484    silent lgrepadd GrepAdd_Autocmd_Text test_quickfix.vim
2485    set grepprg&vim
2486    let l = ['pregrep',
2487		\ 'postgrep',
2488		\ 'pregrepadd',
2489		\ 'postgrepadd',
2490		\ 'pregrep',
2491		\ 'postgrep',
2492		\ 'pregrepadd',
2493		\ 'postgrepadd',
2494		\ 'pregrep',
2495		\ 'postgrep',
2496		\ 'pregrepadd',
2497		\ 'postgrepadd',
2498		\ 'prelgrep',
2499		\ 'postlgrep',
2500		\ 'prelgrepadd',
2501		\ 'postlgrepadd']
2502    call assert_equal(l, g:acmds)
2503  endif
2504
2505  call delete('Xtest')
2506  call delete('Xempty')
2507  au! QuickFixCmdPre
2508  au! QuickFixCmdPost
2509endfunc
2510
2511func Test_Autocmd_Exception()
2512  set efm=%m
2513  lgetexpr '?'
2514
2515  try
2516    call DoesNotExit()
2517  catch
2518    lgetexpr '1'
2519  finally
2520    lgetexpr '1'
2521  endtry
2522
2523  call assert_equal('1', getloclist(0)[0].text)
2524
2525  set efm&vim
2526endfunc
2527
2528func Test_caddbuffer_wrong()
2529  " This used to cause a memory access in freed memory.
2530  let save_efm = &efm
2531  set efm=%EEEE%m,%WWWW,%+CCCC%>%#,%GGGG%.#
2532  cgetexpr ['WWWW', 'EEEE', 'CCCC']
2533  let &efm = save_efm
2534  caddbuffer
2535  bwipe!
2536endfunc
2537
2538func Test_caddexpr_wrong()
2539  " This used to cause a memory access in freed memory.
2540  cbuffer
2541  cbuffer
2542  copen
2543  let save_efm = &efm
2544  set efm=%
2545  call assert_fails('caddexpr ""', 'E376:')
2546  let &efm = save_efm
2547endfunc
2548
2549func Test_dirstack_cleanup()
2550  " This used to cause a memory access in freed memory.
2551  let save_efm = &efm
2552  lexpr '0'
2553  lopen
2554  fun X(c)
2555    let save_efm=&efm
2556    set efm=%D%f
2557    if a:c == 'c'
2558      caddexpr '::'
2559    else
2560      laddexpr ':0:0'
2561    endif
2562    let &efm=save_efm
2563  endfun
2564  call X('c')
2565  call X('l')
2566  call setqflist([], 'r')
2567  caddbuffer
2568  let &efm = save_efm
2569endfunc
2570
2571" Tests for jumping to entries from the location list window and quickfix
2572" window
2573func Test_cwindow_jump()
2574  set efm=%f%%%l%%%m
2575  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2576  lopen | only
2577  lfirst
2578  call assert_true(winnr('$') == 2)
2579  call assert_true(winnr() == 1)
2580  " Location list for the new window should be set
2581  call assert_true(getloclist(0)[2].text == 'Line 30')
2582
2583  " Open a scratch buffer
2584  " Open a new window and create a location list
2585  " Open the location list window and close the other window
2586  " Jump to an entry.
2587  " Should create a new window and jump to the entry. The scratch buffer
2588  " should not be used.
2589  enew | only
2590  set buftype=nofile
2591  below new
2592  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2593  lopen
2594  2wincmd c
2595  lnext
2596  call assert_true(winnr('$') == 3)
2597  call assert_true(winnr() == 2)
2598
2599  " Open two windows with two different location lists
2600  " Open the location list window and close the previous window
2601  " Jump to an entry in the location list window
2602  " Should open the file in the first window and not set the location list.
2603  enew | only
2604  lgetexpr ["F1%5%Line 5"]
2605  below new
2606  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2607  lopen
2608  2wincmd c
2609  lnext
2610  call assert_true(winnr() == 1)
2611  call assert_true(getloclist(0)[0].text == 'Line 5')
2612
2613  enew | only
2614  cgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2615  copen
2616  cnext
2617  call assert_true(winnr('$') == 2)
2618  call assert_true(winnr() == 1)
2619
2620  " open the quickfix buffer in two windows and jump to an entry. Should open
2621  " the file in the first quickfix window.
2622  enew | only
2623  copen
2624  let bnum = bufnr('')
2625  exe 'sbuffer ' . bnum
2626  wincmd b
2627  cfirst
2628  call assert_equal(2, winnr())
2629  call assert_equal('F1', bufname(''))
2630  enew | only
2631  exe 'sb' bnum
2632  exe 'botright sb' bnum
2633  wincmd t
2634  clast
2635  call assert_equal(2, winnr())
2636  call assert_equal('quickfix', getwinvar(1, '&buftype'))
2637  call assert_equal('quickfix', getwinvar(3, '&buftype'))
2638
2639  " Jumping to a file from the location list window should find a usable
2640  " window by wrapping around the window list.
2641  enew | only
2642  call setloclist(0, [], 'f')
2643  new | new
2644  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2645  lopen
2646  1close
2647  call assert_equal(0, getloclist(3, {'id' : 0}).id)
2648  lnext
2649  call assert_equal(3, winnr())
2650  call assert_equal(getloclist(1, {'id' : 0}).id, getloclist(3, {'id' : 0}).id)
2651
2652  enew | only
2653  set efm&vim
2654endfunc
2655
2656func Test_cwindow_highlight()
2657  CheckScreendump
2658
2659  let lines =<< trim END
2660	set t_u7=
2661	call setline(1, ['some', 'text', 'with', 'matches'])
2662	write XCwindow
2663	vimgrep e XCwindow
2664	redraw
2665	cwindow 4
2666  END
2667  call writefile(lines, 'XtestCwindow')
2668  let buf = RunVimInTerminal('-S XtestCwindow', #{rows: 12})
2669  call VerifyScreenDump(buf, 'Test_quickfix_cwindow_1', {})
2670
2671  call term_sendkeys(buf, ":cnext\<CR>")
2672  call VerifyScreenDump(buf, 'Test_quickfix_cwindow_2', {})
2673
2674  " clean up
2675  call StopVimInTerminal(buf)
2676  call delete('XtestCwindow')
2677  call delete('XCwindow')
2678endfunc
2679
2680func XvimgrepTests(cchar)
2681  call s:setup_commands(a:cchar)
2682
2683  call writefile(['Editor:VIM vim',
2684	      \ 'Editor:Emacs EmAcS',
2685	      \ 'Editor:Notepad NOTEPAD'], 'Xtestfile1')
2686  call writefile(['Linux', 'MacOS', 'MS-Windows'], 'Xtestfile2')
2687
2688  " Error cases
2689  call assert_fails('Xvimgrep /abc *', 'E682:')
2690
2691  let @/=''
2692  call assert_fails('Xvimgrep // *', 'E35:')
2693
2694  call assert_fails('Xvimgrep abc', 'E683:')
2695  call assert_fails('Xvimgrep a1b2c3 Xtestfile1', 'E480:')
2696  call assert_fails('Xvimgrep pat Xa1b2c3', 'E480:')
2697
2698  Xexpr ""
2699  Xvimgrepadd Notepad Xtestfile1
2700  Xvimgrepadd MacOS Xtestfile2
2701  let l = g:Xgetlist()
2702  call assert_equal(2, len(l))
2703  call assert_equal('Editor:Notepad NOTEPAD', l[0].text)
2704
2705  10Xvimgrep #\cvim#g Xtestfile?
2706  let l = g:Xgetlist()
2707  call assert_equal(2, len(l))
2708  call assert_equal(8, l[0].col)
2709  call assert_equal(12, l[1].col)
2710
2711  1Xvimgrep ?Editor? Xtestfile*
2712  let l = g:Xgetlist()
2713  call assert_equal(1, len(l))
2714  call assert_equal('Editor:VIM vim', l[0].text)
2715
2716  edit +3 Xtestfile2
2717  Xvimgrep +\cemacs+j Xtestfile1
2718  let l = g:Xgetlist()
2719  call assert_equal('Xtestfile2', bufname(''))
2720  call assert_equal('Editor:Emacs EmAcS', l[0].text)
2721
2722  " Test for unloading a buffer after vimgrep searched the buffer
2723  %bwipe
2724  Xvimgrep /Editor/j Xtestfile*
2725  call assert_equal(0, getbufinfo('Xtestfile1')[0].loaded)
2726  call assert_equal([], getbufinfo('Xtestfile2'))
2727
2728  call delete('Xtestfile1')
2729  call delete('Xtestfile2')
2730endfunc
2731
2732" Tests for the :vimgrep command
2733func Test_vimgrep()
2734  call XvimgrepTests('c')
2735  call XvimgrepTests('l')
2736endfunc
2737
2738" Test for incsearch highlighting of the :vimgrep pattern
2739" This test used to cause "E315: ml_get: invalid lnum" errors.
2740func Test_vimgrep_incsearch()
2741  enew
2742  set incsearch
2743  call test_override("char_avail", 1)
2744
2745  call feedkeys(":2vimgrep assert test_quickfix.vim test_cdo.vim\<CR>", "ntx")
2746  let l = getqflist()
2747  call assert_equal(2, len(l))
2748
2749  call test_override("ALL", 0)
2750  set noincsearch
2751endfunc
2752
2753" Test vimgrep with the last search pattern not set
2754func Test_vimgrep_with_no_last_search_pat()
2755  let lines =<< trim [SCRIPT]
2756    call assert_fails('vimgrep // *', 'E35:')
2757    call writefile(v:errors, 'Xresult')
2758    qall!
2759  [SCRIPT]
2760  call writefile(lines, 'Xscript')
2761  if RunVim([], [], '--clean -S Xscript')
2762    call assert_equal([], readfile('Xresult'))
2763  endif
2764  call delete('Xscript')
2765  call delete('Xresult')
2766endfunc
2767
2768func XfreeTests(cchar)
2769  call s:setup_commands(a:cchar)
2770
2771  enew | only
2772
2773  " Deleting the quickfix stack should work even When the current list is
2774  " somewhere in the middle of the stack
2775  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2776  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2777  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2778  Xolder
2779  call g:Xsetlist([], 'f')
2780  call assert_equal(0, len(g:Xgetlist()))
2781
2782  " After deleting the stack, adding a new list should create a stack with a
2783  " single list.
2784  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2785  call assert_equal(1, g:Xgetlist({'all':1}).nr)
2786
2787  " Deleting the stack from a quickfix window should update/clear the
2788  " quickfix/location list window.
2789  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2790  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2791  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2792  Xolder
2793  Xwindow
2794  call g:Xsetlist([], 'f')
2795  call assert_equal(2, winnr('$'))
2796  call assert_equal(1, line('$'))
2797  Xclose
2798
2799  " Deleting the stack from a non-quickfix window should update/clear the
2800  " quickfix/location list window.
2801  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2802  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2803  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2804  Xolder
2805  Xwindow
2806  wincmd p
2807  call g:Xsetlist([], 'f')
2808  call assert_equal(0, len(g:Xgetlist()))
2809  wincmd p
2810  call assert_equal(2, winnr('$'))
2811  call assert_equal(1, line('$'))
2812
2813  " After deleting the location list stack, if the location list window is
2814  " opened, then a new location list should be created. So opening the
2815  " location list window again should not create a new window.
2816  if a:cchar == 'l'
2817      lexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2818      wincmd p
2819      lopen
2820      call assert_equal(2, winnr('$'))
2821  endif
2822  Xclose
2823endfunc
2824
2825" Tests for the quickfix free functionality
2826func Test_qf_free()
2827  call XfreeTests('c')
2828  call XfreeTests('l')
2829endfunc
2830
2831" Test for buffer overflow when parsing lines and adding new entries to
2832" the quickfix list.
2833func Test_bufoverflow()
2834  set efm=%f:%l:%m
2835  cgetexpr ['File1:100:' . repeat('x', 1025)]
2836
2837  set efm=%+GCompiler:\ %.%#,%f:%l:%m
2838  cgetexpr ['Compiler: ' . repeat('a', 1015), 'File1:10:Hello World']
2839
2840  set efm=%DEntering\ directory\ %f,%f:%l:%m
2841  cgetexpr ['Entering directory ' . repeat('a', 1006),
2842	      \ 'File1:10:Hello World']
2843  set efm&vim
2844endfunc
2845
2846" Tests for getting the quickfix stack size
2847func XsizeTests(cchar)
2848  call s:setup_commands(a:cchar)
2849
2850  call g:Xsetlist([], 'f')
2851  call assert_equal(0, g:Xgetlist({'nr':'$'}).nr)
2852  call assert_equal('', g:Xgetlist({'nr':'$', 'all':1}).title)
2853  call assert_equal(0, g:Xgetlist({'nr':0}).nr)
2854
2855  Xexpr "File1:10:Line1"
2856  Xexpr "File2:20:Line2"
2857  Xexpr "File3:30:Line3"
2858  Xolder | Xolder
2859  call assert_equal(3, g:Xgetlist({'nr':'$'}).nr)
2860  call g:Xsetlist([], 'f')
2861
2862  Xexpr "File1:10:Line1"
2863  Xexpr "File2:20:Line2"
2864  Xexpr "File3:30:Line3"
2865  Xolder | Xolder
2866  call g:Xsetlist([], 'a', {'nr':'$', 'title':'Compiler'})
2867  call assert_equal('Compiler', g:Xgetlist({'nr':3, 'all':1}).title)
2868endfunc
2869
2870func Test_Qf_Size()
2871  call XsizeTests('c')
2872  call XsizeTests('l')
2873endfunc
2874
2875func Test_cclose_from_copen()
2876    augroup QF_Test
2877	au!
2878        au FileType qf :call assert_fails(':cclose', 'E788')
2879    augroup END
2880    copen
2881    augroup QF_Test
2882	au!
2883    augroup END
2884    augroup! QF_Test
2885endfunc
2886
2887func Test_cclose_in_autocmd()
2888  " Problem is only triggered if "starting" is zero, so that the OptionsSet
2889  " event will be triggered.
2890  call test_override('starting', 1)
2891  augroup QF_Test
2892    au!
2893    au FileType qf :call assert_fails(':cclose', 'E788')
2894  augroup END
2895  copen
2896  augroup QF_Test
2897    au!
2898  augroup END
2899  augroup! QF_Test
2900  call test_override('starting', 0)
2901endfunc
2902
2903" Check that ":file" without an argument is possible even when "curbuf_lock"
2904" is set.
2905func Test_file_from_copen()
2906  " Works without argument.
2907  augroup QF_Test
2908    au!
2909    au FileType qf file
2910  augroup END
2911  copen
2912
2913  augroup QF_Test
2914    au!
2915  augroup END
2916  cclose
2917
2918  " Fails with argument.
2919  augroup QF_Test
2920    au!
2921    au FileType qf call assert_fails(':file foo', 'E788')
2922  augroup END
2923  copen
2924  augroup QF_Test
2925    au!
2926  augroup END
2927  cclose
2928
2929  augroup! QF_Test
2930endfunc
2931
2932func Test_resize_from_copen()
2933    augroup QF_Test
2934	au!
2935        au FileType qf resize 5
2936    augroup END
2937    try
2938	" This should succeed without any exception.  No other buffers are
2939	" involved in the autocmd.
2940	copen
2941    finally
2942	augroup QF_Test
2943	    au!
2944	augroup END
2945	augroup! QF_Test
2946    endtry
2947endfunc
2948
2949" Tests for the quickfix buffer b:changedtick variable
2950func Xchangedtick_tests(cchar)
2951  call s:setup_commands(a:cchar)
2952
2953  new | only
2954
2955  Xexpr "" | Xexpr "" | Xexpr ""
2956
2957  Xopen
2958  Xolder
2959  Xolder
2960  Xaddexpr "F1:10:Line10"
2961  Xaddexpr "F2:20:Line20"
2962  call g:Xsetlist([{"filename":"F3", "lnum":30, "text":"Line30"}], 'a')
2963  call g:Xsetlist([], 'f')
2964  call assert_equal(8, getbufvar('%', 'changedtick'))
2965  Xclose
2966endfunc
2967
2968func Test_changedtick()
2969  call Xchangedtick_tests('c')
2970  call Xchangedtick_tests('l')
2971endfunc
2972
2973" Tests for parsing an expression using setqflist()
2974func Xsetexpr_tests(cchar)
2975  call s:setup_commands(a:cchar)
2976
2977  let t = ["File1:10:Line10", "File1:20:Line20"]
2978  call g:Xsetlist([], ' ', {'lines' : t})
2979  call g:Xsetlist([], 'a', {'lines' : ["File1:30:Line30"]})
2980
2981  let l = g:Xgetlist()
2982  call assert_equal(3, len(l))
2983  call assert_equal(20, l[1].lnum)
2984  call assert_equal('Line30', l[2].text)
2985  call g:Xsetlist([], 'r', {'lines' : ["File2:5:Line5"]})
2986  let l = g:Xgetlist()
2987  call assert_equal(1, len(l))
2988  call assert_equal('Line5', l[0].text)
2989  call assert_equal(-1, g:Xsetlist([], 'a', {'lines' : 10}))
2990  call assert_equal(-1, g:Xsetlist([], 'a', {'lines' : "F1:10:L10"}))
2991
2992  call g:Xsetlist([], 'f')
2993  " Add entries to multiple lists
2994  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["File1:10:Line10"]})
2995  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["File2:20:Line20"]})
2996  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["File1:15:Line15"]})
2997  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["File2:25:Line25"]})
2998  call assert_equal('Line15', g:Xgetlist({'nr':1, 'items':1}).items[1].text)
2999  call assert_equal('Line25', g:Xgetlist({'nr':2, 'items':1}).items[1].text)
3000
3001  " Adding entries using a custom efm
3002  set efm&
3003  call g:Xsetlist([], ' ', {'efm' : '%f#%l#%m',
3004				\ 'lines' : ["F1#10#L10", "F2#20#L20"]})
3005  call assert_equal(20, g:Xgetlist({'items':1}).items[1].lnum)
3006  call g:Xsetlist([], 'a', {'efm' : '%f#%l#%m', 'lines' : ["F3:30:L30"]})
3007  call assert_equal('F3:30:L30', g:Xgetlist({'items':1}).items[2].text)
3008  call assert_equal(20, g:Xgetlist({'items':1}).items[1].lnum)
3009  call assert_equal(-1, g:Xsetlist([], 'a', {'efm' : [],
3010				\ 'lines' : ['F1:10:L10']}))
3011endfunc
3012
3013func Test_setexpr()
3014  call Xsetexpr_tests('c')
3015  call Xsetexpr_tests('l')
3016endfunc
3017
3018" Tests for per quickfix/location list directory stack
3019func Xmultidirstack_tests(cchar)
3020  call s:setup_commands(a:cchar)
3021
3022  call g:Xsetlist([], 'f')
3023  Xexpr "" | Xexpr ""
3024
3025  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["Entering dir 'Xone/a'"]})
3026  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["Entering dir 'Xtwo/a'"]})
3027  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["one.txt:3:one one one"]})
3028  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["two.txt:5:two two two"]})
3029
3030  let l1 = g:Xgetlist({'nr':1, 'items':1})
3031  let l2 = g:Xgetlist({'nr':2, 'items':1})
3032  call assert_equal('Xone/a/one.txt', bufname(l1.items[1].bufnr))
3033  call assert_equal(3, l1.items[1].lnum)
3034  call assert_equal('Xtwo/a/two.txt', bufname(l2.items[1].bufnr))
3035  call assert_equal(5, l2.items[1].lnum)
3036endfunc
3037
3038func Test_multidirstack()
3039  call mkdir('Xone/a', 'p')
3040  call mkdir('Xtwo/a', 'p')
3041  let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7']
3042  call writefile(lines, 'Xone/a/one.txt')
3043  call writefile(lines, 'Xtwo/a/two.txt')
3044  let save_efm = &efm
3045  set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f'
3046
3047  call Xmultidirstack_tests('c')
3048  call Xmultidirstack_tests('l')
3049
3050  let &efm = save_efm
3051  call delete('Xone', 'rf')
3052  call delete('Xtwo', 'rf')
3053endfunc
3054
3055" Tests for per quickfix/location list file stack
3056func Xmultifilestack_tests(cchar)
3057  call s:setup_commands(a:cchar)
3058
3059  call g:Xsetlist([], 'f')
3060  Xexpr "" | Xexpr ""
3061
3062  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["[one.txt]"]})
3063  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["[two.txt]"]})
3064  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["(3,5) one one one"]})
3065  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["(5,9) two two two"]})
3066
3067  let l1 = g:Xgetlist({'nr':1, 'items':1})
3068  let l2 = g:Xgetlist({'nr':2, 'items':1})
3069  call assert_equal('one.txt', bufname(l1.items[1].bufnr))
3070  call assert_equal(3, l1.items[1].lnum)
3071  call assert_equal('two.txt', bufname(l2.items[1].bufnr))
3072  call assert_equal(5, l2.items[1].lnum)
3073
3074  " Test for start of a new error line in the same line where a previous
3075  " error line ends with a file stack.
3076  let efm_val = 'Error\ l%l\ in\ %f,'
3077  let efm_val .= '%-P%>(%f%r,Error\ l%l\ in\ %m,%-Q)%r'
3078  let l = g:Xgetlist({'lines' : [
3079	      \ '(one.txt',
3080	      \ 'Error l4 in one.txt',
3081	      \ ') (two.txt',
3082	      \ 'Error l6 in two.txt',
3083	      \ ')',
3084	      \ 'Error l8 in one.txt'
3085	      \ ], 'efm' : efm_val})
3086  call assert_equal(3, len(l.items))
3087  call assert_equal('one.txt', bufname(l.items[0].bufnr))
3088  call assert_equal(4, l.items[0].lnum)
3089  call assert_equal('one.txt', l.items[0].text)
3090  call assert_equal('two.txt', bufname(l.items[1].bufnr))
3091  call assert_equal(6, l.items[1].lnum)
3092  call assert_equal('two.txt', l.items[1].text)
3093  call assert_equal('one.txt', bufname(l.items[2].bufnr))
3094  call assert_equal(8, l.items[2].lnum)
3095  call assert_equal('', l.items[2].text)
3096endfunc
3097
3098func Test_multifilestack()
3099  let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7']
3100  call writefile(lines, 'one.txt')
3101  call writefile(lines, 'two.txt')
3102  let save_efm = &efm
3103  set efm=%+P[%f],(%l\\,%c)\ %m,%-Q
3104
3105  call Xmultifilestack_tests('c')
3106  call Xmultifilestack_tests('l')
3107
3108  let &efm = save_efm
3109  call delete('one.txt')
3110  call delete('two.txt')
3111endfunc
3112
3113" Tests for per buffer 'efm' setting
3114func Test_perbuf_efm()
3115  call writefile(["File1-10-Line10"], 'one.txt')
3116  call writefile(["File2#20#Line20"], 'two.txt')
3117  set efm=%f#%l#%m
3118  new | only
3119  new
3120  setlocal efm=%f-%l-%m
3121  cfile one.txt
3122  wincmd w
3123  caddfile two.txt
3124
3125  let l = getqflist()
3126  call assert_equal(10, l[0].lnum)
3127  call assert_equal('Line20', l[1].text)
3128
3129  set efm&
3130  new | only
3131  call delete('one.txt')
3132  call delete('two.txt')
3133endfunc
3134
3135" Open multiple help windows using ":lhelpgrep
3136" This test used to crash Vim
3137func Test_Multi_LL_Help()
3138    new | only
3139    lhelpgrep window
3140    lopen
3141    e#
3142    lhelpgrep buffer
3143    call assert_equal(3, winnr('$'))
3144    call assert_true(len(getloclist(1)) != 0)
3145    call assert_true(len(getloclist(2)) != 0)
3146    new | only
3147endfunc
3148
3149" Tests for adding new quickfix lists using setqflist()
3150func XaddQf_tests(cchar)
3151  call s:setup_commands(a:cchar)
3152
3153  " Create a new list using ' ' for action
3154  call g:Xsetlist([], 'f')
3155  call g:Xsetlist([], ' ', {'title' : 'Test1'})
3156  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3157  call assert_equal(1, l.nr)
3158  call assert_equal('Test1', l.title)
3159
3160  " Create a new list using ' ' for action and '$' for 'nr'
3161  call g:Xsetlist([], 'f')
3162  call g:Xsetlist([], ' ', {'title' : 'Test2', 'nr' : '$'})
3163  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3164  call assert_equal(1, l.nr)
3165  call assert_equal('Test2', l.title)
3166
3167  " Create a new list using 'a' for action
3168  call g:Xsetlist([], 'f')
3169  call g:Xsetlist([], 'a', {'title' : 'Test3'})
3170  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3171  call assert_equal(1, l.nr)
3172  call assert_equal('Test3', l.title)
3173
3174  " Create a new list using 'a' for action and '$' for 'nr'
3175  call g:Xsetlist([], 'f')
3176  call g:Xsetlist([], 'a', {'title' : 'Test3', 'nr' : '$'})
3177  call g:Xsetlist([], 'a', {'title' : 'Test4'})
3178  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3179  call assert_equal(1, l.nr)
3180  call assert_equal('Test4', l.title)
3181
3182  " Adding a quickfix list should remove all the lists following the current
3183  " list.
3184  Xexpr "" | Xexpr "" | Xexpr ""
3185  silent! 10Xolder
3186  call g:Xsetlist([], ' ', {'title' : 'Test5'})
3187  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3188  call assert_equal(2, l.nr)
3189  call assert_equal('Test5', l.title)
3190
3191  " Add a quickfix list using '$' as the list number.
3192  let lastqf = g:Xgetlist({'nr':'$'}).nr
3193  silent! 99Xolder
3194  call g:Xsetlist([], ' ', {'nr' : '$', 'title' : 'Test6'})
3195  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3196  call assert_equal(lastqf + 1, l.nr)
3197  call assert_equal('Test6', l.title)
3198
3199  " Add a quickfix list using 'nr' set to one more than the quickfix
3200  " list size.
3201  let lastqf = g:Xgetlist({'nr':'$'}).nr
3202  silent! 99Xolder
3203  call g:Xsetlist([], ' ', {'nr' : lastqf + 1, 'title' : 'Test7'})
3204  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3205  call assert_equal(lastqf + 1, l.nr)
3206  call assert_equal('Test7', l.title)
3207
3208  " Add a quickfix list to a stack with 10 lists using 'nr' set to '$'
3209  exe repeat('Xexpr "" |', 9) . 'Xexpr ""'
3210  silent! 99Xolder
3211  call g:Xsetlist([], ' ', {'nr' : '$', 'title' : 'Test8'})
3212  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
3213  call assert_equal(10, l.nr)
3214  call assert_equal('Test8', l.title)
3215
3216  " Add a quickfix list using 'nr' set to a value greater than 10
3217  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : 12, 'title' : 'Test9'}))
3218
3219  " Try adding a quickfix list with 'nr' set to a value greater than the
3220  " quickfix list size but less than 10.
3221  call g:Xsetlist([], 'f')
3222  Xexpr "" | Xexpr "" | Xexpr ""
3223  silent! 99Xolder
3224  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : 8, 'title' : 'Test10'}))
3225
3226  " Add a quickfix list using 'nr' set to a some string or list
3227  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : [1,2], 'title' : 'Test11'}))
3228endfunc
3229
3230func Test_add_qf()
3231  call XaddQf_tests('c')
3232  call XaddQf_tests('l')
3233endfunc
3234
3235" Test for getting the quickfix list items from some text without modifying
3236" the quickfix stack
3237func XgetListFromLines(cchar)
3238  call s:setup_commands(a:cchar)
3239  call g:Xsetlist([], 'f')
3240
3241  let l = g:Xgetlist({'lines' : ["File2:20:Line20", "File2:30:Line30"]}).items
3242  call assert_equal(2, len(l))
3243  call assert_equal(30, l[1].lnum)
3244
3245  call assert_equal({}, g:Xgetlist({'lines' : 10}))
3246  call assert_equal({}, g:Xgetlist({'lines' : 'File1:10:Line10'}))
3247  call assert_equal([], g:Xgetlist({'lines' : []}).items)
3248  call assert_equal([], g:Xgetlist({'lines' : [10, 20]}).items)
3249
3250  " Parse text using a custom efm
3251  set efm&
3252  let l = g:Xgetlist({'lines':['File3#30#Line30'], 'efm' : '%f#%l#%m'}).items
3253  call assert_equal('Line30', l[0].text)
3254  let l = g:Xgetlist({'lines':['File3:30:Line30'], 'efm' : '%f-%l-%m'}).items
3255  call assert_equal('File3:30:Line30', l[0].text)
3256  let l = g:Xgetlist({'lines':['File3:30:Line30'], 'efm' : [1,2]})
3257  call assert_equal({}, l)
3258  call assert_fails("call g:Xgetlist({'lines':['abc'], 'efm':'%2'})", 'E376:')
3259  call assert_fails("call g:Xgetlist({'lines':['abc'], 'efm':''})", 'E378:')
3260
3261  " Make sure that the quickfix stack is not modified
3262  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
3263endfunc
3264
3265func Test_get_list_from_lines()
3266  call XgetListFromLines('c')
3267  call XgetListFromLines('l')
3268endfunc
3269
3270" Tests for the quickfix list id
3271func Xqfid_tests(cchar)
3272  call s:setup_commands(a:cchar)
3273
3274  call g:Xsetlist([], 'f')
3275  call assert_equal(0, g:Xgetlist({'id':0}).id)
3276  Xexpr ''
3277  let start_id = g:Xgetlist({'id' : 0}).id
3278  Xexpr '' | Xexpr ''
3279  Xolder
3280  call assert_equal(start_id, g:Xgetlist({'id':0, 'nr':1}).id)
3281  call assert_equal(start_id + 1, g:Xgetlist({'id':0, 'nr':0}).id)
3282  call assert_equal(start_id + 2, g:Xgetlist({'id':0, 'nr':'$'}).id)
3283  call assert_equal(0, g:Xgetlist({'id':0, 'nr':99}).id)
3284  call assert_equal(2, g:Xgetlist({'id':start_id + 1, 'nr':0}).nr)
3285  call assert_equal(0, g:Xgetlist({'id':99, 'nr':0}).id)
3286  call assert_equal(0, g:Xgetlist({'id':"abc", 'nr':0}).id)
3287
3288  call g:Xsetlist([], 'a', {'id':start_id, 'context':[1,2]})
3289  call assert_equal([1,2], g:Xgetlist({'nr':1, 'context':1}).context)
3290  call g:Xsetlist([], 'a', {'id':start_id+1, 'lines':['F1:10:L10']})
3291  call assert_equal('L10', g:Xgetlist({'nr':2, 'items':1}).items[0].text)
3292  call assert_equal(-1, g:Xsetlist([], 'a', {'id':999, 'title':'Vim'}))
3293  call assert_equal(-1, g:Xsetlist([], 'a', {'id':'abc', 'title':'Vim'}))
3294
3295  let qfid = g:Xgetlist({'id':0, 'nr':0})
3296  call g:Xsetlist([], 'f')
3297  call assert_equal(0, g:Xgetlist({'id':qfid, 'nr':0}).id)
3298endfunc
3299
3300func Test_qf_id()
3301  call Xqfid_tests('c')
3302  call Xqfid_tests('l')
3303endfunc
3304
3305func Xqfjump_tests(cchar)
3306  call s:setup_commands(a:cchar)
3307
3308  call writefile(["Line1\tFoo", "Line2"], 'F1')
3309  call writefile(["Line1\tBar", "Line2"], 'F2')
3310  call writefile(["Line1\tBaz", "Line2"], 'F3')
3311
3312  call g:Xsetlist([], 'f')
3313
3314  " Tests for
3315  "   Jumping to a line using a pattern
3316  "   Jumping to a column greater than the last column in a line
3317  "   Jumping to a line greater than the last line in the file
3318  let l = []
3319  for i in range(1, 7)
3320    call add(l, {})
3321  endfor
3322  let l[0].filename='F1'
3323  let l[0].pattern='Line1'
3324  let l[1].filename='F2'
3325  let l[1].pattern='Line1'
3326  let l[2].filename='F3'
3327  let l[2].pattern='Line1'
3328  let l[3].filename='F3'
3329  let l[3].lnum=1
3330  let l[3].col=9
3331  let l[3].vcol=1
3332  let l[4].filename='F3'
3333  let l[4].lnum=99
3334  let l[5].filename='F3'
3335  let l[5].lnum=1
3336  let l[5].col=99
3337  let l[5].vcol=1
3338  let l[6].filename='F3'
3339  let l[6].pattern='abcxyz'
3340
3341  call g:Xsetlist([], ' ', {'items' : l})
3342  Xopen | only
3343  2Xnext
3344  call assert_equal(3, g:Xgetlist({'idx' : 0}).idx)
3345  call assert_equal('F3', bufname('%'))
3346  Xnext
3347  call assert_equal(7, col('.'))
3348  Xnext
3349  call assert_equal(2, line('.'))
3350  Xnext
3351  call assert_equal(9, col('.'))
3352  2
3353  Xnext
3354  call assert_equal(2, line('.'))
3355
3356  if a:cchar == 'l'
3357    " When jumping to a location list entry in the location list window and
3358    " no usable windows are available, then a new window should be opened.
3359    enew! | new | only
3360    call g:Xsetlist([], 'f')
3361    setlocal buftype=nofile
3362    new
3363    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']})
3364    Xopen
3365    let winid = win_getid()
3366    wincmd p
3367    close
3368    call win_gotoid(winid)
3369    Xnext
3370    call assert_equal(3, winnr('$'))
3371    call assert_equal(1, winnr())
3372    call assert_equal(2, line('.'))
3373
3374    " When jumping to an entry in the location list window and the window
3375    " associated with the location list is not present and a window containing
3376    " the file is already present, then that window should be used.
3377    close
3378    belowright new
3379    call g:Xsetlist([], 'f')
3380    edit F3
3381    call win_gotoid(winid)
3382    Xlast
3383    call assert_equal(3, winnr())
3384    call assert_equal(6, g:Xgetlist({'size' : 1}).size)
3385    call assert_equal(winid, g:Xgetlist({'winid' : 1}).winid)
3386  endif
3387
3388  " Cleanup
3389  enew!
3390  new | only
3391
3392  call delete('F1')
3393  call delete('F2')
3394  call delete('F3')
3395endfunc
3396
3397func Test_qfjump()
3398  call Xqfjump_tests('c')
3399  call Xqfjump_tests('l')
3400endfunc
3401
3402" Tests for the getqflist() and getloclist() functions when the list is not
3403" present or is empty
3404func Xgetlist_empty_tests(cchar)
3405  call s:setup_commands(a:cchar)
3406
3407  " Empty quickfix stack
3408  call g:Xsetlist([], 'f')
3409  call assert_equal('', g:Xgetlist({'context' : 0}).context)
3410  call assert_equal(0, g:Xgetlist({'id' : 0}).id)
3411  call assert_equal(0, g:Xgetlist({'idx' : 0}).idx)
3412  call assert_equal([], g:Xgetlist({'items' : 0}).items)
3413  call assert_equal(0, g:Xgetlist({'nr' : 0}).nr)
3414  call assert_equal(0, g:Xgetlist({'size' : 0}).size)
3415  call assert_equal('', g:Xgetlist({'title' : 0}).title)
3416  call assert_equal(0, g:Xgetlist({'winid' : 0}).winid)
3417  call assert_equal(0, g:Xgetlist({'changedtick' : 0}).changedtick)
3418  if a:cchar == 'c'
3419    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0,
3420		  \ 'items' : [], 'nr' : 0, 'size' : 0, 'qfbufnr' : 0,
3421		  \ 'title' : '', 'winid' : 0, 'changedtick': 0},
3422		  \ g:Xgetlist({'all' : 0}))
3423  else
3424    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0,
3425		\ 'items' : [], 'nr' : 0, 'size' : 0, 'title' : '',
3426		\ 'winid' : 0, 'changedtick': 0, 'filewinid' : 0,
3427		\ 'qfbufnr' : 0},
3428		\ g:Xgetlist({'all' : 0}))
3429  endif
3430
3431  " Quickfix window with empty stack
3432  silent! Xopen
3433  let qfwinid = (a:cchar == 'c') ? win_getid() : 0
3434  let qfbufnr = (a:cchar == 'c') ? bufnr('') : 0
3435  call assert_equal(qfwinid, g:Xgetlist({'winid' : 0}).winid)
3436  Xclose
3437
3438  " Empty quickfix list
3439  Xexpr ""
3440  call assert_equal('', g:Xgetlist({'context' : 0}).context)
3441  call assert_notequal(0, g:Xgetlist({'id' : 0}).id)
3442  call assert_equal(0, g:Xgetlist({'idx' : 0}).idx)
3443  call assert_equal([], g:Xgetlist({'items' : 0}).items)
3444  call assert_notequal(0, g:Xgetlist({'nr' : 0}).nr)
3445  call assert_equal(0, g:Xgetlist({'size' : 0}).size)
3446  call assert_notequal('', g:Xgetlist({'title' : 0}).title)
3447  call assert_equal(0, g:Xgetlist({'winid' : 0}).winid)
3448  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3449
3450  let qfid = g:Xgetlist({'id' : 0}).id
3451  call g:Xsetlist([], 'f')
3452
3453  " Non-existing quickfix identifier
3454  call assert_equal('', g:Xgetlist({'id' : qfid, 'context' : 0}).context)
3455  call assert_equal(0, g:Xgetlist({'id' : qfid}).id)
3456  call assert_equal(0, g:Xgetlist({'id' : qfid, 'idx' : 0}).idx)
3457  call assert_equal([], g:Xgetlist({'id' : qfid, 'items' : 0}).items)
3458  call assert_equal(0, g:Xgetlist({'id' : qfid, 'nr' : 0}).nr)
3459  call assert_equal(0, g:Xgetlist({'id' : qfid, 'size' : 0}).size)
3460  call assert_equal('', g:Xgetlist({'id' : qfid, 'title' : 0}).title)
3461  call assert_equal(0, g:Xgetlist({'id' : qfid, 'winid' : 0}).winid)
3462  call assert_equal(0, g:Xgetlist({'id' : qfid, '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		\ 'qfbufnr' : qfbufnr,
3467		\ 'changedtick' : 0}, g:Xgetlist({'id' : qfid, '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({'id' : qfid, 'all' : 0}))
3473  endif
3474
3475  " Non-existing quickfix list number
3476  call assert_equal('', g:Xgetlist({'nr' : 5, 'context' : 0}).context)
3477  call assert_equal(0, g:Xgetlist({'nr' : 5}).nr)
3478  call assert_equal(0, g:Xgetlist({'nr' : 5, 'idx' : 0}).idx)
3479  call assert_equal([], g:Xgetlist({'nr' : 5, 'items' : 0}).items)
3480  call assert_equal(0, g:Xgetlist({'nr' : 5, 'id' : 0}).id)
3481  call assert_equal(0, g:Xgetlist({'nr' : 5, 'size' : 0}).size)
3482  call assert_equal('', g:Xgetlist({'nr' : 5, 'title' : 0}).title)
3483  call assert_equal(0, g:Xgetlist({'nr' : 5, 'winid' : 0}).winid)
3484  call assert_equal(0, g:Xgetlist({'nr' : 5, 'changedtick' : 0}).changedtick)
3485  if a:cchar == 'c'
3486    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
3487		\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
3488		\ 'changedtick' : 0, 'qfbufnr' : qfbufnr},
3489		\ g:Xgetlist({'nr' : 5, 'all' : 0}))
3490  else
3491    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
3492		\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
3493		\ 'changedtick' : 0, 'filewinid' : 0, 'qfbufnr' : 0},
3494		\ g:Xgetlist({'nr' : 5, 'all' : 0}))
3495  endif
3496endfunc
3497
3498func Test_getqflist()
3499  call Xgetlist_empty_tests('c')
3500  call Xgetlist_empty_tests('l')
3501endfunc
3502
3503func Test_getqflist_invalid_nr()
3504  " The following commands used to crash Vim
3505  cexpr ""
3506  call getqflist({'nr' : $XXX_DOES_NOT_EXIST_XXX})
3507
3508  " Cleanup
3509  call setqflist([], 'r')
3510endfunc
3511
3512" Tests for the quickfix/location list changedtick
3513func Xqftick_tests(cchar)
3514  call s:setup_commands(a:cchar)
3515
3516  call g:Xsetlist([], 'f')
3517
3518  Xexpr "F1:10:Line10"
3519  let qfid = g:Xgetlist({'id' : 0}).id
3520  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3521  Xaddexpr "F2:20:Line20\nF2:21:Line21"
3522  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
3523  call g:Xsetlist([], 'a', {'lines' : ["F3:30:Line30", "F3:31:Line31"]})
3524  call assert_equal(3, g:Xgetlist({'changedtick' : 0}).changedtick)
3525  call g:Xsetlist([], 'r', {'lines' : ["F4:40:Line40"]})
3526  call assert_equal(4, g:Xgetlist({'changedtick' : 0}).changedtick)
3527  call g:Xsetlist([], 'a', {'title' : 'New Title'})
3528  call assert_equal(5, g:Xgetlist({'changedtick' : 0}).changedtick)
3529
3530  enew!
3531  call append(0, ["F5:50:L50", "F6:60:L60"])
3532  Xaddbuffer
3533  call assert_equal(6, g:Xgetlist({'changedtick' : 0}).changedtick)
3534  enew!
3535
3536  call g:Xsetlist([], 'a', {'context' : {'bus' : 'pci'}})
3537  call assert_equal(7, g:Xgetlist({'changedtick' : 0}).changedtick)
3538  call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'},
3539	      \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], 'a')
3540  call assert_equal(8, g:Xgetlist({'changedtick' : 0}).changedtick)
3541  call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'},
3542	      \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], ' ')
3543  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3544  call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'},
3545	      \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], 'r')
3546  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
3547
3548  call writefile(["F8:80:L80", "F8:81:L81"], "Xone")
3549  Xfile Xone
3550  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3551  Xaddfile Xone
3552  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
3553
3554  " Test case for updating a non-current quickfix list
3555  call g:Xsetlist([], 'f')
3556  Xexpr "F1:1:L1"
3557  Xexpr "F2:2:L2"
3558  call g:Xsetlist([], 'a', {'nr' : 1, "lines" : ["F10:10:L10"]})
3559  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3560  call assert_equal(2, g:Xgetlist({'nr' : 1, 'changedtick' : 0}).changedtick)
3561
3562  call delete("Xone")
3563endfunc
3564
3565func Test_qf_tick()
3566  call Xqftick_tests('c')
3567  call Xqftick_tests('l')
3568endfunc
3569
3570" Test helpgrep with lang specifier
3571func Xtest_helpgrep_with_lang_specifier(cchar)
3572  call s:setup_commands(a:cchar)
3573  Xhelpgrep Vim@en
3574  call assert_equal('help', &filetype)
3575  call assert_notequal(0, g:Xgetlist({'nr' : '$'}).nr)
3576  new | only
3577endfunc
3578
3579func Test_helpgrep_with_lang_specifier()
3580  call Xtest_helpgrep_with_lang_specifier('c')
3581  call Xtest_helpgrep_with_lang_specifier('l')
3582endfunc
3583
3584" The following test used to crash Vim.
3585" Open the location list window and close the regular window associated with
3586" the location list. When the garbage collection runs now, it incorrectly
3587" marks the location list context as not in use and frees the context.
3588func Test_ll_window_ctx()
3589  call setloclist(0, [], 'f')
3590  call setloclist(0, [], 'a', {'context' : []})
3591  lopen | only
3592  call test_garbagecollect_now()
3593  echo getloclist(0, {'context' : 1}).context
3594  enew | only
3595endfunc
3596
3597" The following test used to crash vim
3598func Test_lfile_crash()
3599  sp Xtest
3600  au QuickFixCmdPre * bw
3601  call assert_fails('lfile', 'E40')
3602  au! QuickFixCmdPre
3603endfunc
3604
3605" The following test used to crash vim
3606func Test_lbuffer_crash()
3607  sv Xtest
3608  augroup QF_Test
3609    au!
3610    au * * bw
3611  augroup END
3612  lbuffer
3613  augroup QF_Test
3614    au!
3615  augroup END
3616endfunc
3617
3618" The following test used to crash vim
3619func Test_lexpr_crash()
3620  augroup QF_Test
3621    au!
3622    au * * call setloclist(0, [], 'f')
3623  augroup END
3624  lexpr ""
3625  augroup QF_Test
3626    au!
3627  augroup END
3628
3629  enew | only
3630  augroup QF_Test
3631    au!
3632    au BufNew * call setloclist(0, [], 'f')
3633  augroup END
3634  lexpr 'x:1:x'
3635  augroup QF_Test
3636    au!
3637  augroup END
3638
3639  enew | only
3640  lexpr ''
3641  lopen
3642  augroup QF_Test
3643    au!
3644    au FileType * call setloclist(0, [], 'f')
3645  augroup END
3646  lexpr ''
3647  augroup QF_Test
3648    au!
3649  augroup END
3650endfunc
3651
3652" The following test used to crash Vim
3653func Test_lvimgrep_crash()
3654  sv Xtest
3655  augroup QF_Test
3656    au!
3657    au * * call setloclist(0, [], 'f')
3658  augroup END
3659  lvimgrep quickfix test_quickfix.vim
3660  augroup QF_Test
3661    au!
3662  augroup END
3663
3664  new | only
3665  augroup QF_Test
3666    au!
3667    au BufEnter * call setloclist(0, [], 'r')
3668  augroup END
3669  call assert_fails('lvimgrep Test_lvimgrep_crash *', 'E926:')
3670  augroup QF_Test
3671    au!
3672  augroup END
3673
3674  enew | only
3675endfunc
3676
3677" Test for the position of the quickfix and location list window
3678func Test_qfwin_pos()
3679  " Open two windows
3680  new | only
3681  new
3682  cexpr ['F1:10:L10']
3683  copen
3684  " Quickfix window should be the bottom most window
3685  call assert_equal(3, winnr())
3686  close
3687  " Open at the very top
3688  wincmd t
3689  topleft copen
3690  call assert_equal(1, winnr())
3691  close
3692  " open left of the current window
3693  wincmd t
3694  below new
3695  leftabove copen
3696  call assert_equal(2, winnr())
3697  close
3698  " open right of the current window
3699  rightbelow copen
3700  call assert_equal(3, winnr())
3701  close
3702endfunc
3703
3704" Tests for quickfix/location lists changed by autocommands when
3705" :vimgrep/:lvimgrep commands are running.
3706func Test_vimgrep_autocmd()
3707  call setqflist([], 'f')
3708  call writefile(['stars'], 'Xtest1.txt')
3709  call writefile(['stars'], 'Xtest2.txt')
3710
3711  " Test 1:
3712  " When searching for a pattern using :vimgrep, if the quickfix list is
3713  " changed by an autocmd, the results should be added to the correct quickfix
3714  " list.
3715  autocmd BufRead Xtest2.txt cexpr '' | cexpr ''
3716  silent vimgrep stars Xtest*.txt
3717  call assert_equal(1, getqflist({'nr' : 0}).nr)
3718  call assert_equal(3, getqflist({'nr' : '$'}).nr)
3719  call assert_equal('Xtest2.txt', bufname(getqflist()[1].bufnr))
3720  au! BufRead Xtest2.txt
3721
3722  " Test 2:
3723  " When searching for a pattern using :vimgrep, if the quickfix list is
3724  " freed, then a error should be given.
3725  silent! %bwipe!
3726  call setqflist([], 'f')
3727  autocmd BufRead Xtest2.txt for i in range(10) | cexpr '' | endfor
3728  call assert_fails('vimgrep stars Xtest*.txt', 'E925:')
3729  au! BufRead Xtest2.txt
3730
3731  " Test 3:
3732  " When searching for a pattern using :lvimgrep, if the location list is
3733  " freed, then the command should error out.
3734  silent! %bwipe!
3735  let g:save_winid = win_getid()
3736  autocmd BufRead Xtest2.txt call setloclist(g:save_winid, [], 'f')
3737  call assert_fails('lvimgrep stars Xtest*.txt', 'E926:')
3738  au! BufRead Xtest2.txt
3739
3740  call delete('Xtest1.txt')
3741  call delete('Xtest2.txt')
3742  call setqflist([], 'f')
3743endfunc
3744
3745" Test for an autocmd changing the current directory when running vimgrep
3746func Xvimgrep_autocmd_cd(cchar)
3747  call s:setup_commands(a:cchar)
3748
3749  %bwipe
3750  let save_cwd = getcwd()
3751
3752  augroup QF_Test
3753    au!
3754    autocmd BufRead * silent cd %:p:h
3755  augroup END
3756
3757  10Xvimgrep /vim/ Xdir/**
3758  let l = g:Xgetlist()
3759  call assert_equal('f1.txt', bufname(l[0].bufnr))
3760  call assert_equal('f2.txt', fnamemodify(bufname(l[2].bufnr), ':t'))
3761
3762  augroup QF_Test
3763    au!
3764  augroup END
3765
3766  exe 'cd ' . save_cwd
3767endfunc
3768
3769func Test_vimgrep_autocmd_cd()
3770  call mkdir('Xdir/a', 'p')
3771  call mkdir('Xdir/b', 'p')
3772  call writefile(['a_L1_vim', 'a_L2_vim'], 'Xdir/a/f1.txt')
3773  call writefile(['b_L1_vim', 'b_L2_vim'], 'Xdir/b/f2.txt')
3774  call Xvimgrep_autocmd_cd('c')
3775  call Xvimgrep_autocmd_cd('l')
3776  %bwipe
3777  call delete('Xdir', 'rf')
3778endfunc
3779
3780" The following test used to crash Vim
3781func Test_lhelpgrep_autocmd()
3782  lhelpgrep quickfix
3783  autocmd QuickFixCmdPost * call setloclist(0, [], 'f')
3784  lhelpgrep buffer
3785  call assert_equal('help', &filetype)
3786  call assert_equal(0, getloclist(0, {'nr' : '$'}).nr)
3787  lhelpgrep tabpage
3788  call assert_equal('help', &filetype)
3789  call assert_equal(1, getloclist(0, {'nr' : '$'}).nr)
3790  au! QuickFixCmdPost
3791
3792  new | only
3793  augroup QF_Test
3794    au!
3795    au BufEnter * call setqflist([], 'f')
3796  augroup END
3797  call assert_fails('helpgrep quickfix', 'E925:')
3798  augroup QF_Test
3799    au! BufEnter
3800  augroup END
3801
3802  new | only
3803  augroup QF_Test
3804    au!
3805    au BufEnter * call setqflist([], 'r')
3806  augroup END
3807  call assert_fails('helpgrep quickfix', 'E925:')
3808  augroup QF_Test
3809    au! BufEnter
3810  augroup END
3811
3812  new | only
3813  augroup QF_Test
3814    au!
3815    au BufEnter * call setloclist(0, [], 'r')
3816  augroup END
3817  call assert_fails('lhelpgrep quickfix', 'E926:')
3818  augroup QF_Test
3819    au! BufEnter
3820  augroup END
3821
3822  new | only
3823endfunc
3824
3825" Test for shortening/simplifying the file name when opening the
3826" quickfix window or when displaying the quickfix list
3827func Test_shorten_fname()
3828  if !has('unix')
3829    return
3830  endif
3831  %bwipe
3832  " Create a quickfix list with a absolute path filename
3833  let fname = getcwd() . '/test_quickfix.vim'
3834  call setqflist([], ' ', {'lines':[fname . ":20:Line20"], 'efm':'%f:%l:%m'})
3835  call assert_equal(fname, bufname('test_quickfix.vim'))
3836  " Opening the quickfix window should simplify the file path
3837  cwindow
3838  call assert_equal('test_quickfix.vim', bufname('test_quickfix.vim'))
3839  cclose
3840  %bwipe
3841  " Create a quickfix list with a absolute path filename
3842  call setqflist([], ' ', {'lines':[fname . ":20:Line20"], 'efm':'%f:%l:%m'})
3843  call assert_equal(fname, bufname('test_quickfix.vim'))
3844  " Displaying the quickfix list should simplify the file path
3845  silent! clist
3846  call assert_equal('test_quickfix.vim', bufname('test_quickfix.vim'))
3847endfunc
3848
3849" Quickfix title tests
3850" In the below tests, 'exe "cmd"' is used to invoke the quickfix commands.
3851" Otherwise due to indentation, the title is set with spaces at the beginning
3852" of the command.
3853func Test_qftitle()
3854  call writefile(["F1:1:Line1"], 'Xerr')
3855
3856  " :cexpr
3857  exe "cexpr readfile('Xerr')"
3858  call assert_equal(":cexpr readfile('Xerr')", getqflist({'title' : 1}).title)
3859
3860  " :cgetexpr
3861  exe "cgetexpr readfile('Xerr')"
3862  call assert_equal(":cgetexpr readfile('Xerr')",
3863					\ getqflist({'title' : 1}).title)
3864
3865  " :caddexpr
3866  call setqflist([], 'f')
3867  exe "caddexpr readfile('Xerr')"
3868  call assert_equal(":caddexpr readfile('Xerr')",
3869					\ getqflist({'title' : 1}).title)
3870
3871  " :cbuffer
3872  new Xerr
3873  exe "cbuffer"
3874  call assert_equal(':cbuffer (Xerr)', getqflist({'title' : 1}).title)
3875
3876  " :cgetbuffer
3877  edit Xerr
3878  exe "cgetbuffer"
3879  call assert_equal(':cgetbuffer (Xerr)', getqflist({'title' : 1}).title)
3880
3881  " :caddbuffer
3882  call setqflist([], 'f')
3883  edit Xerr
3884  exe "caddbuffer"
3885  call assert_equal(':caddbuffer (Xerr)', getqflist({'title' : 1}).title)
3886
3887  " :cfile
3888  exe "cfile Xerr"
3889  call assert_equal(':cfile Xerr', getqflist({'title' : 1}).title)
3890
3891  " :cgetfile
3892  exe "cgetfile Xerr"
3893  call assert_equal(':cgetfile Xerr', getqflist({'title' : 1}).title)
3894
3895  " :caddfile
3896  call setqflist([], 'f')
3897  exe "caddfile Xerr"
3898  call assert_equal(':caddfile Xerr', getqflist({'title' : 1}).title)
3899
3900  " :grep
3901  set grepprg=internal
3902  exe "grep F1 Xerr"
3903  call assert_equal(':grep F1 Xerr', getqflist({'title' : 1}).title)
3904
3905  " :grepadd
3906  call setqflist([], 'f')
3907  exe "grepadd F1 Xerr"
3908  call assert_equal(':grepadd F1 Xerr', getqflist({'title' : 1}).title)
3909  set grepprg&vim
3910
3911  " :vimgrep
3912  exe "vimgrep F1 Xerr"
3913  call assert_equal(':vimgrep F1 Xerr', getqflist({'title' : 1}).title)
3914
3915  " :vimgrepadd
3916  call setqflist([], 'f')
3917  exe "vimgrepadd F1 Xerr"
3918  call assert_equal(':vimgrepadd F1 Xerr', getqflist({'title' : 1}).title)
3919
3920  call setqflist(['F1:10:L10'], ' ')
3921  call assert_equal(':setqflist()', getqflist({'title' : 1}).title)
3922
3923  call setqflist([], 'f')
3924  call setqflist(['F1:10:L10'], 'a')
3925  call assert_equal(':setqflist()', getqflist({'title' : 1}).title)
3926
3927  call setqflist([], 'f')
3928  call setqflist(['F1:10:L10'], 'r')
3929  call assert_equal(':setqflist()', getqflist({'title' : 1}).title)
3930
3931  close
3932  call delete('Xerr')
3933
3934  call setqflist([], ' ', {'title' : 'Errors'})
3935  copen
3936  call assert_equal('Errors', w:quickfix_title)
3937  call setqflist([], 'r', {'items' : [{'filename' : 'a.c', 'lnum' : 10}]})
3938  call assert_equal('Errors', w:quickfix_title)
3939  cclose
3940endfunc
3941
3942func Test_lbuffer_with_bwipe()
3943  new
3944  new
3945  augroup nasty
3946    au * * bwipe
3947  augroup END
3948  lbuffer
3949  augroup nasty
3950    au!
3951  augroup END
3952endfunc
3953
3954" Test for an autocmd freeing the quickfix/location list when cexpr/lexpr is
3955" running
3956func Xexpr_acmd_freelist(cchar)
3957  call s:setup_commands(a:cchar)
3958
3959  " This was using freed memory.
3960  augroup nasty
3961    au * * call g:Xsetlist([], 'f')
3962  augroup END
3963  Xexpr "x"
3964  augroup nasty
3965    au!
3966  augroup END
3967endfunc
3968
3969func Test_cexpr_acmd_freelist()
3970  call Xexpr_acmd_freelist('c')
3971  call Xexpr_acmd_freelist('l')
3972endfunc
3973
3974" Test for commands that create a new quickfix/location list and jump to the
3975" first error automatically.
3976func Xjumpto_first_error_test(cchar)
3977  call s:setup_commands(a:cchar)
3978
3979  call s:create_test_file('Xtestfile1')
3980  call s:create_test_file('Xtestfile2')
3981  let l = ['Xtestfile1:2:Line2', 'Xtestfile2:4:Line4']
3982
3983  " Test for cexpr/lexpr
3984  enew
3985  Xexpr l
3986  call assert_equal('Xtestfile1', bufname(''))
3987  call assert_equal(2, line('.'))
3988
3989  " Test for cfile/lfile
3990  enew
3991  call writefile(l, 'Xerr')
3992  Xfile Xerr
3993  call assert_equal('Xtestfile1', bufname(''))
3994  call assert_equal(2, line('.'))
3995
3996  " Test for cbuffer/lbuffer
3997  edit Xerr
3998  Xbuffer
3999  call assert_equal('Xtestfile1', bufname(''))
4000  call assert_equal(2, line('.'))
4001
4002  call delete('Xerr')
4003  call delete('Xtestfile1')
4004  call delete('Xtestfile2')
4005endfunc
4006
4007func Test_jumpto_first_error()
4008  call Xjumpto_first_error_test('c')
4009  call Xjumpto_first_error_test('l')
4010endfunc
4011
4012" Test for a quickfix autocmd changing the quickfix/location list before
4013" jumping to the first error in the new list.
4014func Xautocmd_changelist(cchar)
4015  call s:setup_commands(a:cchar)
4016
4017  " Test for cfile/lfile
4018  call s:create_test_file('Xtestfile1')
4019  call s:create_test_file('Xtestfile2')
4020  Xexpr 'Xtestfile1:2:Line2'
4021  autocmd QuickFixCmdPost * Xolder
4022  call writefile(['Xtestfile2:4:Line4'], 'Xerr')
4023  Xfile Xerr
4024  call assert_equal('Xtestfile2', bufname(''))
4025  call assert_equal(4, line('.'))
4026  autocmd! QuickFixCmdPost
4027
4028  " Test for cbuffer/lbuffer
4029  call g:Xsetlist([], 'f')
4030  Xexpr 'Xtestfile1:2:Line2'
4031  autocmd QuickFixCmdPost * Xolder
4032  call writefile(['Xtestfile2:4:Line4'], 'Xerr')
4033  edit Xerr
4034  Xbuffer
4035  call assert_equal('Xtestfile2', bufname(''))
4036  call assert_equal(4, line('.'))
4037  autocmd! QuickFixCmdPost
4038
4039  " Test for cexpr/lexpr
4040  call g:Xsetlist([], 'f')
4041  Xexpr 'Xtestfile1:2:Line2'
4042  autocmd QuickFixCmdPost * Xolder
4043  Xexpr 'Xtestfile2:4:Line4'
4044  call assert_equal('Xtestfile2', bufname(''))
4045  call assert_equal(4, line('.'))
4046  autocmd! QuickFixCmdPost
4047
4048  " The grepprg may not be set on non-Unix systems
4049  if has('unix')
4050    " Test for grep/lgrep
4051    call g:Xsetlist([], 'f')
4052    Xexpr 'Xtestfile1:2:Line2'
4053    autocmd QuickFixCmdPost * Xolder
4054    silent Xgrep Line5 Xtestfile2
4055    call assert_equal('Xtestfile2', bufname(''))
4056    call assert_equal(5, line('.'))
4057    autocmd! QuickFixCmdPost
4058  endif
4059
4060  " Test for vimgrep/lvimgrep
4061  call g:Xsetlist([], 'f')
4062  Xexpr 'Xtestfile1:2:Line2'
4063  autocmd QuickFixCmdPost * Xolder
4064  silent Xvimgrep Line5 Xtestfile2
4065  call assert_equal('Xtestfile2', bufname(''))
4066  call assert_equal(5, line('.'))
4067  autocmd! QuickFixCmdPost
4068
4069  " Test for autocommands clearing the quickfix list before jumping to the
4070  " first error. This should not result in an error
4071  autocmd QuickFixCmdPost * call g:Xsetlist([], 'r')
4072  let v:errmsg = ''
4073  " Test for cfile/lfile
4074  Xfile Xerr
4075  call assert_true(v:errmsg !~# 'E42:')
4076  " Test for cbuffer/lbuffer
4077  edit Xerr
4078  Xbuffer
4079  call assert_true(v:errmsg !~# 'E42:')
4080  " Test for cexpr/lexpr
4081  Xexpr 'Xtestfile2:4:Line4'
4082  call assert_true(v:errmsg !~# 'E42:')
4083  " Test for grep/lgrep
4084  " The grepprg may not be set on non-Unix systems
4085  if has('unix')
4086    silent Xgrep Line5 Xtestfile2
4087    call assert_true(v:errmsg !~# 'E42:')
4088  endif
4089  " Test for vimgrep/lvimgrep
4090  call assert_fails('silent Xvimgrep Line5 Xtestfile2', 'E480:')
4091  autocmd! QuickFixCmdPost
4092
4093  call delete('Xerr')
4094  call delete('Xtestfile1')
4095  call delete('Xtestfile2')
4096endfunc
4097
4098func Test_autocmd_changelist()
4099  call Xautocmd_changelist('c')
4100  call Xautocmd_changelist('l')
4101endfunc
4102
4103" Tests for the ':filter /pat/ clist' command
4104func Test_filter_clist()
4105  cexpr ['Xfile1:10:10:Line 10', 'Xfile2:15:15:Line 15']
4106  call assert_equal([' 2 Xfile2:15 col 15: Line 15'],
4107			\ split(execute('filter /Line 15/ clist'), "\n"))
4108  call assert_equal([' 1 Xfile1:10 col 10: Line 10'],
4109			\ split(execute('filter /Xfile1/ clist'), "\n"))
4110  call assert_equal([], split(execute('filter /abc/ clist'), "\n"))
4111
4112  call setqflist([{'module' : 'abc', 'pattern' : 'pat1'},
4113			\ {'module' : 'pqr', 'pattern' : 'pat2'}], ' ')
4114  call assert_equal([' 2 pqr:pat2:  '],
4115			\ split(execute('filter /pqr/ clist'), "\n"))
4116  call assert_equal([' 1 abc:pat1:  '],
4117			\ split(execute('filter /pat1/ clist'), "\n"))
4118endfunc
4119
4120" Tests for the "CTRL-W <CR>" command.
4121func Xview_result_split_tests(cchar)
4122  call s:setup_commands(a:cchar)
4123
4124  " Test that "CTRL-W <CR>" in a qf/ll window fails with empty list.
4125  call g:Xsetlist([])
4126  Xopen
4127  let l:win_count = winnr('$')
4128  call assert_fails('execute "normal! \<C-W>\<CR>"', 'E42')
4129  call assert_equal(l:win_count, winnr('$'))
4130  Xclose
4131endfunc
4132
4133func Test_view_result_split()
4134  call Xview_result_split_tests('c')
4135  call Xview_result_split_tests('l')
4136endfunc
4137
4138" Test that :cc sets curswant
4139func Test_curswant()
4140  helpgrep quickfix
4141  normal! llll
4142  1cc
4143  call assert_equal(getcurpos()[4], virtcol('.'))
4144  cclose | helpclose
4145endfunc
4146
4147" Test for opening a file from the quickfix window using CTRL-W <Enter>
4148" doesn't leave an empty buffer around.
4149func Test_splitview()
4150  call s:create_test_file('Xtestfile1')
4151  call s:create_test_file('Xtestfile2')
4152  new | only
4153  let last_bufnr = bufnr('Test_sv_1', 1)
4154  let l = ['Xtestfile1:2:Line2', 'Xtestfile2:4:Line4']
4155  cgetexpr l
4156  copen
4157  let numbufs = len(getbufinfo())
4158  exe "normal \<C-W>\<CR>"
4159  copen
4160  exe "normal j\<C-W>\<CR>"
4161  " Make sure new empty buffers are not created
4162  call assert_equal(numbufs, len(getbufinfo()))
4163  " Creating a new buffer should use the next available buffer number
4164  call assert_equal(last_bufnr + 4, bufnr("Test_sv_2", 1))
4165  bwipe Test_sv_1
4166  bwipe Test_sv_2
4167  new | only
4168
4169  " When split opening files from location list window, make sure that two
4170  " windows doesn't refer to the same location list
4171  lgetexpr l
4172  let locid = getloclist(0, {'id' : 0}).id
4173  lopen
4174  exe "normal \<C-W>\<CR>"
4175  call assert_notequal(locid, getloclist(0, {'id' : 0}).id)
4176  call assert_equal(0, getloclist(0, {'winid' : 0}).winid)
4177  new | only
4178
4179  " When split opening files from a helpgrep location list window, a new help
4180  " window should be opened with a copy of the location list.
4181  lhelpgrep window
4182  let locid = getloclist(0, {'id' : 0}).id
4183  lwindow
4184  exe "normal j\<C-W>\<CR>"
4185  call assert_notequal(locid, getloclist(0, {'id' : 0}).id)
4186  call assert_equal(0, getloclist(0, {'winid' : 0}).winid)
4187  new | only
4188
4189  call delete('Xtestfile1')
4190  call delete('Xtestfile2')
4191endfunc
4192
4193" Test for parsing entries using visual screen column
4194func Test_viscol()
4195  enew
4196  call writefile(["Col1\tCol2\tCol3"], 'Xfile1')
4197  edit Xfile1
4198
4199  " Use byte offset for column number
4200  set efm&
4201  cexpr "Xfile1:1:5:XX\nXfile1:1:9:YY\nXfile1:1:20:ZZ"
4202  call assert_equal([5, 8], [col('.'), virtcol('.')])
4203  cnext
4204  call assert_equal([9, 12], [col('.'), virtcol('.')])
4205  cnext
4206  call assert_equal([14, 20], [col('.'), virtcol('.')])
4207
4208  " Use screen column offset for column number
4209  set efm=%f:%l:%v:%m
4210  cexpr "Xfile1:1:8:XX\nXfile1:1:12:YY\nXfile1:1:20:ZZ"
4211  call assert_equal([5, 8], [col('.'), virtcol('.')])
4212  cnext
4213  call assert_equal([9, 12], [col('.'), virtcol('.')])
4214  cnext
4215  call assert_equal([14, 20], [col('.'), virtcol('.')])
4216  cexpr "Xfile1:1:6:XX\nXfile1:1:15:YY\nXfile1:1:24:ZZ"
4217  call assert_equal([5, 8], [col('.'), virtcol('.')])
4218  cnext
4219  call assert_equal([10, 16], [col('.'), virtcol('.')])
4220  cnext
4221  call assert_equal([14, 20], [col('.'), virtcol('.')])
4222
4223  enew
4224  call writefile(["Col1\täü\töß\tCol4"], 'Xfile1')
4225
4226  " Use byte offset for column number
4227  set efm&
4228  cexpr "Xfile1:1:8:XX\nXfile1:1:11:YY\nXfile1:1:16:ZZ"
4229  call assert_equal([8, 10], [col('.'), virtcol('.')])
4230  cnext
4231  call assert_equal([11, 17], [col('.'), virtcol('.')])
4232  cnext
4233  call assert_equal([16, 25], [col('.'), virtcol('.')])
4234
4235  " Use screen column offset for column number
4236  set efm=%f:%l:%v:%m
4237  cexpr "Xfile1:1:10:XX\nXfile1:1:17:YY\nXfile1:1:25:ZZ"
4238  call assert_equal([8, 10], [col('.'), virtcol('.')])
4239  cnext
4240  call assert_equal([11, 17], [col('.'), virtcol('.')])
4241  cnext
4242  call assert_equal([16, 25], [col('.'), virtcol('.')])
4243
4244  enew | only
4245  set efm&
4246  call delete('Xfile1')
4247endfunc
4248
4249" Test for the quickfix window buffer
4250func Xqfbuf_test(cchar)
4251  call s:setup_commands(a:cchar)
4252
4253  " Quickfix buffer should be reused across closing and opening a quickfix
4254  " window
4255  Xexpr "F1:10:Line10"
4256  Xopen
4257  let qfbnum = bufnr('')
4258  Xclose
4259  " Even after the quickfix window is closed, the buffer should be loaded
4260  call assert_true(bufloaded(qfbnum))
4261  call assert_true(qfbnum, g:Xgetlist({'qfbufnr' : 0}).qfbufnr)
4262  Xopen
4263  " Buffer should be reused when opening the window again
4264  call assert_equal(qfbnum, bufnr(''))
4265  Xclose
4266
4267  if a:cchar == 'l'
4268    %bwipe
4269    " For a location list, when both the file window and the location list
4270    " window for the list are closed, then the buffer should be freed.
4271    new | only
4272    lexpr "F1:10:Line10"
4273    let wid = win_getid()
4274    lopen
4275    let qfbnum = bufnr('')
4276    call assert_match(qfbnum . ' %a-  "\[Location List]"', execute('ls'))
4277    close
4278    " When the location list window is closed, the buffer name should not
4279    " change to 'Quickfix List'
4280    call assert_match(qfbnum . 'u h-  "\[Location List]"', execute('ls!'))
4281    call assert_true(bufloaded(qfbnum))
4282
4283    " After deleting a location list buffer using ":bdelete", opening the
4284    " location list window should mark the buffer as a location list buffer.
4285    exe "bdelete " . qfbnum
4286    lopen
4287    call assert_equal("quickfix", &buftype)
4288    call assert_equal(1, getwininfo(win_getid(winnr()))[0].loclist)
4289    call assert_equal(wid, getloclist(0, {'filewinid' : 0}).filewinid)
4290    call assert_false(&swapfile)
4291    lclose
4292
4293    " When the location list is cleared for the window, the buffer should be
4294    " removed
4295    call setloclist(0, [], 'f')
4296    call assert_false(bufexists(qfbnum))
4297    call assert_equal(0, getloclist(0, {'qfbufnr' : 0}).qfbufnr)
4298
4299    " When the location list is freed with the location list window open, the
4300    " location list buffer should not be lost. It should be reused when the
4301    " location list is again populated.
4302    lexpr "F1:10:Line10"
4303    lopen
4304    let wid = win_getid()
4305    let qfbnum = bufnr('')
4306    wincmd p
4307    call setloclist(0, [], 'f')
4308    lexpr "F1:10:Line10"
4309    lopen
4310    call assert_equal(wid, win_getid())
4311    call assert_equal(qfbnum, bufnr(''))
4312    lclose
4313
4314    " When the window with the location list is closed, the buffer should be
4315    " removed
4316    new | only
4317    call assert_false(bufexists(qfbnum))
4318  endif
4319endfunc
4320
4321func Test_qfbuf()
4322  call Xqfbuf_test('c')
4323  call Xqfbuf_test('l')
4324endfunc
4325
4326" If there is an autocmd to use only one window, then opening the location
4327" list window used to crash Vim.
4328func Test_winonly_autocmd()
4329  call s:create_test_file('Xtest1')
4330  " Autocmd to show only one Vim window at a time
4331  autocmd WinEnter * only
4332  new
4333  " Load the location list
4334  lexpr "Xtest1:5:Line5\nXtest1:10:Line10\nXtest1:15:Line15"
4335  let loclistid = getloclist(0, {'id' : 0}).id
4336  " Open the location list window. Only this window will be shown and the file
4337  " window is closed.
4338  lopen
4339  call assert_equal(loclistid, getloclist(0, {'id' : 0}).id)
4340  " Jump to an entry in the location list and make sure that the cursor is
4341  " positioned correctly.
4342  ll 3
4343  call assert_equal(loclistid, getloclist(0, {'id' : 0}).id)
4344  call assert_equal('Xtest1', bufname(''))
4345  call assert_equal(15, line('.'))
4346  " Cleanup
4347  autocmd! WinEnter
4348  new | only
4349  call delete('Xtest1')
4350endfunc
4351
4352" Test to make sure that an empty quickfix buffer is not reused for loading
4353" a normal buffer.
4354func Test_empty_qfbuf()
4355  enew | only
4356  call writefile(["Test"], 'Xfile1')
4357  call setqflist([], 'f')
4358  copen | only
4359  let qfbuf = bufnr('')
4360  edit Xfile1
4361  call assert_notequal(qfbuf, bufnr(''))
4362  enew
4363  call delete('Xfile1')
4364endfunc
4365
4366" Test for the :cbelow, :cabove, :lbelow and :labove commands.
4367" And for the :cafter, :cbefore, :lafter and :lbefore commands.
4368func Xtest_below(cchar)
4369  call s:setup_commands(a:cchar)
4370
4371  " No quickfix/location list
4372  call assert_fails('Xbelow', 'E42:')
4373  call assert_fails('Xabove', 'E42:')
4374  call assert_fails('Xbefore', 'E42:')
4375  call assert_fails('Xafter', 'E42:')
4376
4377  " Empty quickfix/location list
4378  call g:Xsetlist([])
4379  call assert_fails('Xbelow', 'E42:')
4380  call assert_fails('Xabove', 'E42:')
4381  call assert_fails('Xbefore', 'E42:')
4382  call assert_fails('Xafter', 'E42:')
4383
4384  call s:create_test_file('X1')
4385  call s:create_test_file('X2')
4386  call s:create_test_file('X3')
4387  call s:create_test_file('X4')
4388
4389  " Invalid entries
4390  edit X1
4391  call g:Xsetlist(["E1", "E2"])
4392  call assert_fails('Xbelow', 'E42:')
4393  call assert_fails('Xabove', 'E42:')
4394  call assert_fails('3Xbelow', 'E42:')
4395  call assert_fails('4Xabove', 'E42:')
4396  call assert_fails('Xbefore', 'E42:')
4397  call assert_fails('Xafter', 'E42:')
4398  call assert_fails('3Xbefore', 'E42:')
4399  call assert_fails('4Xafter', 'E42:')
4400
4401  " Test the commands with various arguments
4402  Xexpr ["X1:5:3:L5", "X2:5:2:L5", "X2:10:3:L10", "X2:15:4:L15", "X3:3:5:L3"]
4403  edit +7 X2
4404  Xabove
4405  call assert_equal(['X2', 5], [bufname(''), line('.')])
4406  call assert_fails('Xabove', 'E553:')
4407  normal 7G
4408  Xbefore
4409  call assert_equal(['X2', 5, 2], [bufname(''), line('.'), col('.')])
4410  call assert_fails('Xbefore', 'E553:')
4411
4412  normal 2j
4413  Xbelow
4414  call assert_equal(['X2', 10], [bufname(''), line('.')])
4415  normal 7G
4416  Xafter
4417  call assert_equal(['X2', 10, 3], [bufname(''), line('.'), col('.')])
4418
4419  " Last error in this file
4420  Xbelow 99
4421  call assert_equal(['X2', 15], [bufname(''), line('.')])
4422  call assert_fails('Xbelow', 'E553:')
4423  normal gg
4424  Xafter 99
4425  call assert_equal(['X2', 15, 4], [bufname(''), line('.'), col('.')])
4426  call assert_fails('Xafter', 'E553:')
4427
4428  " First error in this file
4429  Xabove 99
4430  call assert_equal(['X2', 5], [bufname(''), line('.')])
4431  call assert_fails('Xabove', 'E553:')
4432  normal G
4433  Xbefore 99
4434  call assert_equal(['X2', 5, 2], [bufname(''), line('.'), col('.')])
4435  call assert_fails('Xbefore', 'E553:')
4436
4437  normal gg
4438  Xbelow 2
4439  call assert_equal(['X2', 10], [bufname(''), line('.')])
4440  normal gg
4441  Xafter 2
4442  call assert_equal(['X2', 10, 3], [bufname(''), line('.'), col('.')])
4443
4444  normal G
4445  Xabove 2
4446  call assert_equal(['X2', 10], [bufname(''), line('.')])
4447  normal G
4448  Xbefore 2
4449  call assert_equal(['X2', 10, 3], [bufname(''), line('.'), col('.')])
4450
4451  edit X4
4452  call assert_fails('Xabove', 'E42:')
4453  call assert_fails('Xbelow', 'E42:')
4454  call assert_fails('Xbefore', 'E42:')
4455  call assert_fails('Xafter', 'E42:')
4456  if a:cchar == 'l'
4457    " If a buffer has location list entries from some other window but not
4458    " from the current window, then the commands should fail.
4459    edit X1 | split | call setloclist(0, [], 'f')
4460    call assert_fails('Xabove', 'E776:')
4461    call assert_fails('Xbelow', 'E776:')
4462    call assert_fails('Xbefore', 'E776:')
4463    call assert_fails('Xafter', 'E776:')
4464    close
4465  endif
4466
4467  " Test for lines with multiple quickfix entries
4468  Xexpr ["X1:5:L5", "X2:5:1:L5_1", "X2:5:2:L5_2", "X2:5:3:L5_3",
4469	      \ "X2:10:1:L10_1", "X2:10:2:L10_2", "X2:10:3:L10_3",
4470	      \ "X2:15:1:L15_1", "X2:15:2:L15_2", "X2:15:3:L15_3", "X3:3:L3"]
4471  edit +1 X2
4472  Xbelow 2
4473  call assert_equal(['X2', 10, 1], [bufname(''), line('.'), col('.')])
4474  normal 1G
4475  Xafter 2
4476  call assert_equal(['X2', 5, 2], [bufname(''), line('.'), col('.')])
4477
4478  normal gg
4479  Xbelow 99
4480  call assert_equal(['X2', 15, 1], [bufname(''), line('.'), col('.')])
4481  normal gg
4482  Xafter 99
4483  call assert_equal(['X2', 15, 3], [bufname(''), line('.'), col('.')])
4484
4485  normal G
4486  Xabove 2
4487  call assert_equal(['X2', 10, 1], [bufname(''), line('.'), col('.')])
4488  normal G
4489  Xbefore 2
4490  call assert_equal(['X2', 15, 2], [bufname(''), line('.'), col('.')])
4491
4492  normal G
4493  Xabove 99
4494  call assert_equal(['X2', 5, 1], [bufname(''), line('.'), col('.')])
4495  normal G
4496  Xbefore 99
4497  call assert_equal(['X2', 5, 1], [bufname(''), line('.'), col('.')])
4498
4499  normal 10G
4500  Xabove
4501  call assert_equal(['X2', 5, 1], [bufname(''), line('.'), col('.')])
4502  normal 10G$
4503  2Xbefore
4504  call assert_equal(['X2', 10, 2], [bufname(''), line('.'), col('.')])
4505
4506  normal 10G
4507  Xbelow
4508  call assert_equal(['X2', 15, 1], [bufname(''), line('.'), col('.')])
4509  normal 9G
4510  5Xafter
4511  call assert_equal(['X2', 15, 2], [bufname(''), line('.'), col('.')])
4512
4513  " Invalid range
4514  if a:cchar == 'c'
4515    call assert_fails('-2cbelow', 'E16:')
4516    call assert_fails('-2cafter', 'E16:')
4517  else
4518    call assert_fails('-2lbelow', 'E16:')
4519    call assert_fails('-2lafter', 'E16:')
4520  endif
4521
4522  call delete('X1')
4523  call delete('X2')
4524  call delete('X3')
4525  call delete('X4')
4526endfunc
4527
4528func Test_cbelow()
4529  call Xtest_below('c')
4530  call Xtest_below('l')
4531endfunc
4532
4533func Test_quickfix_count()
4534  let commands = [
4535	\ 'cNext',
4536	\ 'cNfile',
4537	\ 'cabove',
4538	\ 'cbelow',
4539	\ 'cfirst',
4540	\ 'clast',
4541	\ 'cnewer',
4542	\ 'cnext',
4543	\ 'cnfile',
4544	\ 'colder',
4545	\ 'cprevious',
4546	\ 'crewind',
4547	\
4548	\ 'lNext',
4549	\ 'lNfile',
4550	\ 'labove',
4551	\ 'lbelow',
4552	\ 'lfirst',
4553	\ 'llast',
4554	\ 'lnewer',
4555	\ 'lnext',
4556	\ 'lnfile',
4557	\ 'lolder',
4558	\ 'lprevious',
4559	\ 'lrewind',
4560	\ ]
4561  for cmd in commands
4562    call assert_fails('-1' .. cmd, 'E16:')
4563    call assert_fails('.' .. cmd, 'E16:')
4564    call assert_fails('%' .. cmd, 'E16:')
4565    call assert_fails('$' .. cmd, 'E16:')
4566  endfor
4567endfunc
4568
4569" Test for aborting quickfix commands using QuickFixCmdPre
4570func Xtest_qfcmd_abort(cchar)
4571  call s:setup_commands(a:cchar)
4572
4573  call g:Xsetlist([], 'f')
4574
4575  " cexpr/lexpr
4576  let e = ''
4577  try
4578    Xexpr ["F1:10:Line10", "F2:20:Line20"]
4579  catch /.*/
4580    let e = v:exception
4581  endtry
4582  call assert_equal('AbortCmd', e)
4583  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4584
4585  " cfile/lfile
4586  call writefile(["F1:10:Line10", "F2:20:Line20"], 'Xfile1')
4587  let e = ''
4588  try
4589    Xfile Xfile1
4590  catch /.*/
4591    let e = v:exception
4592  endtry
4593  call assert_equal('AbortCmd', e)
4594  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4595  call delete('Xfile1')
4596
4597  " cgetbuffer/lgetbuffer
4598  enew!
4599  call append(0, ["F1:10:Line10", "F2:20:Line20"])
4600  let e = ''
4601  try
4602    Xgetbuffer
4603  catch /.*/
4604    let e = v:exception
4605  endtry
4606  call assert_equal('AbortCmd', e)
4607  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4608  enew!
4609
4610  " vimgrep/lvimgrep
4611  let e = ''
4612  try
4613    Xvimgrep /func/ test_quickfix.vim
4614  catch /.*/
4615    let e = v:exception
4616  endtry
4617  call assert_equal('AbortCmd', e)
4618  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4619
4620  " helpgrep/lhelpgrep
4621  let e = ''
4622  try
4623    Xhelpgrep quickfix
4624  catch /.*/
4625    let e = v:exception
4626  endtry
4627  call assert_equal('AbortCmd', e)
4628  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4629
4630  " grep/lgrep
4631  if has('unix')
4632    let e = ''
4633    try
4634      silent Xgrep func test_quickfix.vim
4635    catch /.*/
4636      let e = v:exception
4637    endtry
4638    call assert_equal('AbortCmd', e)
4639    call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
4640  endif
4641endfunc
4642
4643func Test_qfcmd_abort()
4644  augroup QF_Test
4645    au!
4646    autocmd  QuickFixCmdPre * throw "AbortCmd"
4647  augroup END
4648
4649  call Xtest_qfcmd_abort('c')
4650  call Xtest_qfcmd_abort('l')
4651
4652  augroup QF_Test
4653    au!
4654  augroup END
4655endfunc
4656
4657" Test for using a file in one of the parent directories.
4658func Test_search_in_dirstack()
4659  call mkdir('Xtestdir/a/b/c', 'p')
4660  let save_cwd = getcwd()
4661  call writefile(["X1_L1", "X1_L2"], 'Xtestdir/Xfile1')
4662  call writefile(["X2_L1", "X2_L2"], 'Xtestdir/a/Xfile2')
4663  call writefile(["X3_L1", "X3_L2"], 'Xtestdir/a/b/Xfile3')
4664  call writefile(["X4_L1", "X4_L2"], 'Xtestdir/a/b/c/Xfile4')
4665
4666  let lines = "Entering dir Xtestdir\n" .
4667	      \ "Entering dir a\n" .
4668	      \ "Entering dir b\n" .
4669	      \ "Xfile2:2:X2_L2\n" .
4670	      \ "Leaving dir a\n" .
4671	      \ "Xfile1:2:X1_L2\n" .
4672	      \ "Xfile3:1:X3_L1\n" .
4673	      \ "Entering dir c\n" .
4674	      \ "Xfile4:2:X4_L2\n" .
4675	      \ "Leaving dir c\n"
4676  set efm=%DEntering\ dir\ %f,%XLeaving\ dir\ %f,%f:%l:%m
4677  cexpr lines .. "Leaving dir Xtestdir|\n" | let next = 1
4678  call assert_equal(11, getqflist({'size' : 0}).size)
4679  call assert_equal(4, getqflist({'idx' : 0}).idx)
4680  call assert_equal('X2_L2', getline('.'))
4681  call assert_equal(1, next)
4682  cnext
4683  call assert_equal(6, getqflist({'idx' : 0}).idx)
4684  call assert_equal('X1_L2', getline('.'))
4685  cnext
4686  call assert_equal(7, getqflist({'idx' : 0}).idx)
4687  call assert_equal(1, line('$'))
4688  call assert_equal('', getline(1))
4689  cnext
4690  call assert_equal(9, getqflist({'idx' : 0}).idx)
4691  call assert_equal(1, line('$'))
4692  call assert_equal('', getline(1))
4693
4694  set efm&
4695  exe 'cd ' . save_cwd
4696  call delete('Xtestdir', 'rf')
4697endfunc
4698
4699" Test for :cquit
4700func Test_cquit()
4701  " Exit Vim with a non-zero value
4702  if RunVim([], ["cquit 7"], '')
4703    call assert_equal(7, v:shell_error)
4704  endif
4705
4706  if RunVim([], ["50cquit"], '')
4707    call assert_equal(50, v:shell_error)
4708  endif
4709
4710  " Exit Vim with default value
4711  if RunVim([], ["cquit"], '')
4712    call assert_equal(1, v:shell_error)
4713  endif
4714
4715  " Exit Vim with zero value
4716  if RunVim([], ["cquit 0"], '')
4717    call assert_equal(0, v:shell_error)
4718  endif
4719
4720  " Exit Vim with negative value
4721  call assert_fails('-3cquit', 'E16:')
4722endfunc
4723
4724" vim: shiftwidth=2 sts=2 expandtab
4725