1" Test for the quickfix commands.
2
3if !has('quickfix')
4  finish
5endif
6
7set encoding=utf-8
8
9func s:setup_commands(cchar)
10  if a:cchar == 'c'
11    command! -nargs=* -bang Xlist <mods>clist<bang> <args>
12    command! -nargs=* Xgetexpr <mods>cgetexpr <args>
13    command! -nargs=* Xaddexpr <mods>caddexpr <args>
14    command! -nargs=* Xolder <mods>colder <args>
15    command! -nargs=* Xnewer <mods>cnewer <args>
16    command! -nargs=* Xopen <mods>copen <args>
17    command! -nargs=* Xwindow <mods>cwindow <args>
18    command! -nargs=* Xbottom <mods>cbottom <args>
19    command! -nargs=* Xclose <mods>cclose <args>
20    command! -nargs=* -bang Xfile <mods>cfile<bang> <args>
21    command! -nargs=* Xgetfile <mods>cgetfile <args>
22    command! -nargs=* Xaddfile <mods>caddfile <args>
23    command! -nargs=* -bang Xbuffer <mods>cbuffer<bang> <args>
24    command! -nargs=* Xgetbuffer <mods>cgetbuffer <args>
25    command! -nargs=* Xaddbuffer <mods>caddbuffer <args>
26    command! -nargs=* Xrewind <mods>crewind <args>
27    command! -count -nargs=* -bang Xnext <mods><count>cnext<bang> <args>
28    command! -count -nargs=* -bang Xprev <mods><count>cprev<bang> <args>
29    command! -nargs=* -bang Xfirst <mods>cfirst<bang> <args>
30    command! -nargs=* -bang Xlast <mods>clast<bang> <args>
31    command! -nargs=* -bang Xnfile <mods>cnfile<bang> <args>
32    command! -nargs=* -bang Xpfile <mods>cpfile<bang> <args>
33    command! -nargs=* Xexpr <mods>cexpr <args>
34    command! -range -nargs=* Xvimgrep <mods><count>vimgrep <args>
35    command! -nargs=* Xvimgrepadd <mods>vimgrepadd <args>
36    command! -nargs=* Xgrep <mods> grep <args>
37    command! -nargs=* Xgrepadd <mods> grepadd <args>
38    command! -nargs=* Xhelpgrep helpgrep <args>
39    let g:Xgetlist = function('getqflist')
40    let g:Xsetlist = function('setqflist')
41    call setqflist([], 'f')
42  else
43    command! -nargs=* -bang Xlist <mods>llist<bang> <args>
44    command! -nargs=* Xgetexpr <mods>lgetexpr <args>
45    command! -nargs=* Xaddexpr <mods>laddexpr <args>
46    command! -nargs=* Xolder <mods>lolder <args>
47    command! -nargs=* Xnewer <mods>lnewer <args>
48    command! -nargs=* Xopen <mods>lopen <args>
49    command! -nargs=* Xwindow <mods>lwindow <args>
50    command! -nargs=* Xbottom <mods>lbottom <args>
51    command! -nargs=* Xclose <mods>lclose <args>
52    command! -nargs=* -bang Xfile <mods>lfile<bang> <args>
53    command! -nargs=* Xgetfile <mods>lgetfile <args>
54    command! -nargs=* Xaddfile <mods>laddfile <args>
55    command! -nargs=* -bang Xbuffer <mods>lbuffer<bang> <args>
56    command! -nargs=* Xgetbuffer <mods>lgetbuffer <args>
57    command! -nargs=* Xaddbuffer <mods>laddbuffer <args>
58    command! -nargs=* Xrewind <mods>lrewind <args>
59    command! -count -nargs=* -bang Xnext <mods><count>lnext<bang> <args>
60    command! -count -nargs=* -bang Xprev <mods><count>lprev<bang> <args>
61    command! -nargs=* -bang Xfirst <mods>lfirst<bang> <args>
62    command! -nargs=* -bang Xlast <mods>llast<bang> <args>
63    command! -nargs=* -bang Xnfile <mods>lnfile<bang> <args>
64    command! -nargs=* -bang Xpfile <mods>lpfile<bang> <args>
65    command! -nargs=* Xexpr <mods>lexpr <args>
66    command! -range -nargs=* Xvimgrep <mods><count>lvimgrep <args>
67    command! -nargs=* Xvimgrepadd <mods>lvimgrepadd <args>
68    command! -nargs=* Xgrep <mods> lgrep <args>
69    command! -nargs=* Xgrepadd <mods> lgrepadd <args>
70    command! -nargs=* Xhelpgrep lhelpgrep <args>
71    let g:Xgetlist = function('getloclist', [0])
72    let g:Xsetlist = function('setloclist', [0])
73    call setloclist(0, [], 'f')
74  endif
75endfunc
76
77" Tests for the :clist and :llist commands
78func XlistTests(cchar)
79  call s:setup_commands(a:cchar)
80
81  if a:cchar == 'l'
82      call assert_fails('llist', 'E776:')
83  endif
84  " With an empty list, command should return error
85  Xgetexpr []
86  silent! Xlist
87  call assert_true(v:errmsg ==# 'E42: No Errors')
88
89  " Populate the list and then try
90  Xgetexpr ['non-error 1', 'Xtestfile1:1:3:Line1',
91		  \ 'non-error 2', 'Xtestfile2:2:2:Line2',
92		  \ 'non-error 3', 'Xtestfile3:3:1:Line3']
93
94  " List only valid entries
95  let l = split(execute('Xlist', ''), "\n")
96  call assert_equal([' 2 Xtestfile1:1 col 3: Line1',
97		   \ ' 4 Xtestfile2:2 col 2: Line2',
98		   \ ' 6 Xtestfile3:3 col 1: Line3'], l)
99
100  " List all the entries
101  let l = split(execute('Xlist!', ''), "\n")
102  call assert_equal([' 1: non-error 1', ' 2 Xtestfile1:1 col 3: Line1',
103		   \ ' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2',
104		   \ ' 5: non-error 3', ' 6 Xtestfile3:3 col 1: Line3'], l)
105
106  " List a range of errors
107  let l = split(execute('Xlist 3,6', ''), "\n")
108  call assert_equal([' 4 Xtestfile2:2 col 2: Line2',
109		   \ ' 6 Xtestfile3:3 col 1: Line3'], l)
110
111  let l = split(execute('Xlist! 3,4', ''), "\n")
112  call assert_equal([' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2'], l)
113
114  let l = split(execute('Xlist -6,-4', ''), "\n")
115  call assert_equal([' 2 Xtestfile1:1 col 3: Line1'], l)
116
117  let l = split(execute('Xlist! -5,-3', ''), "\n")
118  call assert_equal([' 2 Xtestfile1:1 col 3: Line1',
119		   \ ' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2'], l)
120
121  " Test for '+'
122  let l = split(execute('Xlist! +2', ''), "\n")
123  call assert_equal([' 2 Xtestfile1:1 col 3: Line1',
124		   \ ' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2'], l)
125
126  " Different types of errors
127  call g:Xsetlist([{'lnum':10,'col':5,'type':'W', 'text':'Warning','nr':11},
128	      \ {'lnum':20,'col':10,'type':'e','text':'Error','nr':22},
129	      \ {'lnum':30,'col':15,'type':'i','text':'Info','nr':33},
130	      \ {'lnum':40,'col':20,'type':'x', 'text':'Other','nr':44},
131	      \ {'lnum':50,'col':25,'type':"\<C-A>",'text':'one','nr':55}])
132  let l = split(execute('Xlist', ""), "\n")
133  call assert_equal([' 1:10 col 5 warning  11: Warning',
134	      \ ' 2:20 col 10 error  22: Error',
135	      \ ' 3:30 col 15 info  33: Info',
136	      \ ' 4:40 col 20 x  44: Other',
137	      \ ' 5:50 col 25  55: one'], l)
138
139  " Error cases
140  call assert_fails('Xlist abc', 'E488:')
141endfunc
142
143func Test_clist()
144  call XlistTests('c')
145  call XlistTests('l')
146endfunc
147
148" Tests for the :colder, :cnewer, :lolder and :lnewer commands
149" Note that this test assumes that a quickfix/location list is
150" already set by the caller.
151func XageTests(cchar)
152  call s:setup_commands(a:cchar)
153
154  let list = [{'bufnr': 1, 'lnum': 1}]
155  call g:Xsetlist(list)
156
157  " Jumping to a non existent list should return error
158  silent! Xolder 99
159  call assert_true(v:errmsg ==# 'E380: At bottom of quickfix stack')
160
161  silent! Xnewer 99
162  call assert_true(v:errmsg ==# 'E381: At top of quickfix stack')
163
164  " Add three quickfix/location lists
165  Xgetexpr ['Xtestfile1:1:3:Line1']
166  Xgetexpr ['Xtestfile2:2:2:Line2']
167  Xgetexpr ['Xtestfile3:3:1:Line3']
168
169  " Go back two lists
170  Xolder
171  let l = g:Xgetlist()
172  call assert_equal('Line2', l[0].text)
173
174  " Go forward two lists
175  Xnewer
176  let l = g:Xgetlist()
177  call assert_equal('Line3', l[0].text)
178
179  " Test for the optional count argument
180  Xolder 2
181  let l = g:Xgetlist()
182  call assert_equal('Line1', l[0].text)
183
184  Xnewer 2
185  let l = g:Xgetlist()
186  call assert_equal('Line3', l[0].text)
187endfunc
188
189func Test_cage()
190  call XageTests('c')
191  call XageTests('l')
192endfunc
193
194" Tests for the :cwindow, :lwindow :cclose, :lclose, :copen and :lopen
195" commands
196func XwindowTests(cchar)
197  call s:setup_commands(a:cchar)
198
199  " Opening the location list window without any errors should fail
200  if a:cchar == 'l'
201      call assert_fails('lopen', 'E776:')
202  endif
203
204  " Create a list with no valid entries
205  Xgetexpr ['non-error 1', 'non-error 2', 'non-error 3']
206
207  " Quickfix/Location window should not open with no valid errors
208  Xwindow
209  call assert_true(winnr('$') == 1)
210
211  " Create a list with valid entries
212  Xgetexpr ['Xtestfile1:1:3:Line1', 'Xtestfile2:2:2:Line2',
213		  \ 'Xtestfile3:3:1:Line3']
214
215  " Open the window
216  Xwindow
217  call assert_true(winnr('$') == 2 && winnr() == 2 &&
218	\ getline('.') ==# 'Xtestfile1|1 col 3| Line1')
219  redraw!
220
221  " Close the window
222  Xclose
223  call assert_true(winnr('$') == 1)
224
225  " Create a list with no valid entries
226  Xgetexpr ['non-error 1', 'non-error 2', 'non-error 3']
227
228  " Open the window
229  Xopen 5
230  call assert_true(winnr('$') == 2 && getline('.') ==# '|| non-error 1'
231		      \  && winheight('.') == 5)
232
233  " Opening the window again, should move the cursor to that window
234  wincmd t
235  Xopen 7
236  call assert_true(winnr('$') == 2 && winnr() == 2 &&
237	\ winheight('.') == 7 &&
238	\ getline('.') ==# '|| non-error 1')
239
240
241  " Calling cwindow should close the quickfix window with no valid errors
242  Xwindow
243  call assert_true(winnr('$') == 1)
244
245  if a:cchar == 'c'
246      " Opening the quickfix window in multiple tab pages should reuse the
247      " quickfix buffer
248      Xgetexpr ['Xtestfile1:1:3:Line1', 'Xtestfile2:2:2:Line2',
249		  \ 'Xtestfile3:3:1:Line3']
250      Xopen
251      let qfbufnum = bufnr('%')
252      tabnew
253      Xopen
254      call assert_equal(qfbufnum, bufnr('%'))
255      new | only | tabonly
256  endif
257endfunc
258
259func Test_cwindow()
260  call XwindowTests('c')
261  call XwindowTests('l')
262endfunc
263
264" Tests for the :cfile, :lfile, :caddfile, :laddfile, :cgetfile and :lgetfile
265" commands.
266func XfileTests(cchar)
267  call s:setup_commands(a:cchar)
268
269  call writefile(['Xtestfile1:700:10:Line 700',
270	\ 'Xtestfile2:800:15:Line 800'], 'Xqftestfile1')
271
272  enew!
273  Xfile Xqftestfile1
274  let l = g:Xgetlist()
275  call assert_true(len(l) == 2 &&
276	\ l[0].lnum == 700 && l[0].col == 10 && l[0].text ==# 'Line 700' &&
277	\ l[1].lnum == 800 && l[1].col == 15 && l[1].text ==# 'Line 800')
278
279  " Test with a non existent file
280  call assert_fails('Xfile non_existent_file', 'E40')
281
282  " Run cfile/lfile from a modified buffer
283  enew!
284  silent! put ='Quickfix'
285  silent! Xfile Xqftestfile1
286  call assert_true(v:errmsg ==# 'E37: No write since last change (add ! to override)')
287
288  call writefile(['Xtestfile3:900:30:Line 900'], 'Xqftestfile1')
289  Xaddfile Xqftestfile1
290  let l = g:Xgetlist()
291  call assert_true(len(l) == 3 &&
292	\ l[2].lnum == 900 && l[2].col == 30 && l[2].text ==# 'Line 900')
293
294  call writefile(['Xtestfile1:222:77:Line 222',
295	\ 'Xtestfile2:333:88:Line 333'], 'Xqftestfile1')
296
297  enew!
298  Xgetfile Xqftestfile1
299  let l = g:Xgetlist()
300  call assert_true(len(l) == 2 &&
301	\ l[0].lnum == 222 && l[0].col == 77 && l[0].text ==# 'Line 222' &&
302	\ l[1].lnum == 333 && l[1].col == 88 && l[1].text ==# 'Line 333')
303
304  call delete('Xqftestfile1')
305endfunc
306
307func Test_cfile()
308  call XfileTests('c')
309  call XfileTests('l')
310endfunc
311
312" Tests for the :cbuffer, :lbuffer, :caddbuffer, :laddbuffer, :cgetbuffer and
313" :lgetbuffer commands.
314func XbufferTests(cchar)
315  call s:setup_commands(a:cchar)
316
317  enew!
318  silent! call setline(1, ['Xtestfile7:700:10:Line 700',
319	\ 'Xtestfile8:800:15:Line 800'])
320  Xbuffer!
321  let l = g:Xgetlist()
322  call assert_true(len(l) == 2 &&
323	\ l[0].lnum == 700 && l[0].col == 10 && l[0].text ==# 'Line 700' &&
324	\ l[1].lnum == 800 && l[1].col == 15 && l[1].text ==# 'Line 800')
325
326  enew!
327  silent! call setline(1, ['Xtestfile9:900:55:Line 900',
328	\ 'Xtestfile10:950:66:Line 950'])
329  Xgetbuffer
330  let l = g:Xgetlist()
331  call assert_true(len(l) == 2 &&
332	\ l[0].lnum == 900 && l[0].col == 55 && l[0].text ==# 'Line 900' &&
333	\ l[1].lnum == 950 && l[1].col == 66 && l[1].text ==# 'Line 950')
334
335  enew!
336  silent! call setline(1, ['Xtestfile11:700:20:Line 700',
337	\ 'Xtestfile12:750:25:Line 750'])
338  Xaddbuffer
339  let l = g:Xgetlist()
340  call assert_true(len(l) == 4 &&
341	\ l[1].lnum == 950 && l[1].col == 66 && l[1].text ==# 'Line 950' &&
342	\ l[2].lnum == 700 && l[2].col == 20 && l[2].text ==# 'Line 700' &&
343	\ l[3].lnum == 750 && l[3].col == 25 && l[3].text ==# 'Line 750')
344  enew!
345
346  " Check for invalid buffer
347  call assert_fails('Xbuffer 199', 'E474:')
348
349  " Check for unloaded buffer
350  edit Xtestfile1
351  let bnr = bufnr('%')
352  enew!
353  call assert_fails('Xbuffer ' . bnr, 'E681:')
354
355  " Check for invalid range
356  " Using Xbuffer will not run the range check in the cbuffer/lbuffer
357  " commands. So directly call the commands.
358  if (a:cchar == 'c')
359      call assert_fails('900,999cbuffer', 'E16:')
360  else
361      call assert_fails('900,999lbuffer', 'E16:')
362  endif
363endfunc
364
365func Test_cbuffer()
366  call XbufferTests('c')
367  call XbufferTests('l')
368endfunc
369
370func XexprTests(cchar)
371  call s:setup_commands(a:cchar)
372
373  call assert_fails('Xexpr 10', 'E777:')
374endfunc
375
376func Test_cexpr()
377  call XexprTests('c')
378  call XexprTests('l')
379endfunc
380
381" Tests for :cnext, :cprev, :cfirst, :clast commands
382func Xtest_browse(cchar)
383  call s:setup_commands(a:cchar)
384
385  " Jumping to first or next location list entry without any error should
386  " result in failure
387  if a:cchar == 'l'
388      call assert_fails('lfirst', 'E776:')
389      call assert_fails('lnext', 'E776:')
390  endif
391
392  call s:create_test_file('Xqftestfile1')
393  call s:create_test_file('Xqftestfile2')
394
395  Xgetexpr ['Xqftestfile1:5:Line5',
396		\ 'Xqftestfile1:6:Line6',
397		\ 'Xqftestfile2:10:Line10',
398		\ 'Xqftestfile2:11:Line11',
399		\ 'RegularLine1',
400		\ 'RegularLine2']
401
402  Xfirst
403  call assert_fails('Xprev', 'E553')
404  call assert_fails('Xpfile', 'E553')
405  Xnfile
406  call assert_equal('Xqftestfile2', bufname('%'))
407  call assert_equal(10, line('.'))
408  Xpfile
409  call assert_equal('Xqftestfile1', bufname('%'))
410  call assert_equal(6, line('.'))
411  Xlast
412  Xprev
413  call assert_equal('Xqftestfile2', bufname('%'))
414  call assert_equal(11, line('.'))
415  call assert_fails('Xnext', 'E553')
416  call assert_fails('Xnfile', 'E553')
417  Xrewind
418  call assert_equal('Xqftestfile1', bufname('%'))
419  call assert_equal(5, line('.'))
420
421  10Xnext
422  call assert_equal('Xqftestfile2', bufname('%'))
423  call assert_equal(11, line('.'))
424  10Xprev
425  call assert_equal('Xqftestfile1', bufname('%'))
426  call assert_equal(5, line('.'))
427
428  Xexpr ""
429  call assert_fails('Xnext', 'E42:')
430
431  call delete('Xqftestfile1')
432  call delete('Xqftestfile2')
433endfunc
434
435func Test_browse()
436  call Xtest_browse('c')
437  call Xtest_browse('l')
438endfunc
439
440func Test_nomem()
441  call test_alloc_fail(GetAllocId('qf_dirname_start'), 0, 0)
442  call assert_fails('vimgrep vim runtest.vim', 'E342:')
443
444  call test_alloc_fail(GetAllocId('qf_dirname_now'), 0, 0)
445  call assert_fails('vimgrep vim runtest.vim', 'E342:')
446
447  call test_alloc_fail(GetAllocId('qf_namebuf'), 0, 0)
448  call assert_fails('cfile runtest.vim', 'E342:')
449
450  call test_alloc_fail(GetAllocId('qf_errmsg'), 0, 0)
451  call assert_fails('cfile runtest.vim', 'E342:')
452
453  call test_alloc_fail(GetAllocId('qf_pattern'), 0, 0)
454  call assert_fails('cfile runtest.vim', 'E342:')
455
456endfunc
457
458func s:test_xhelpgrep(cchar)
459  call s:setup_commands(a:cchar)
460  Xhelpgrep quickfix
461  Xopen
462  if a:cchar == 'c'
463    let title_text = ':helpgrep quickfix'
464  else
465    let title_text = ':lhelpgrep quickfix'
466  endif
467  call assert_true(w:quickfix_title =~ title_text, w:quickfix_title)
468
469  " Jumping to a help topic should open the help window
470  only
471  Xnext
472  call assert_true(&buftype == 'help')
473  call assert_true(winnr('$') == 2)
474  " Jumping to the next match should reuse the help window
475  Xnext
476  call assert_true(&buftype == 'help')
477  call assert_true(winnr() == 1)
478  call assert_true(winnr('$') == 2)
479  " Jumping to the next match from the quickfix window should reuse the help
480  " window
481  Xopen
482  Xnext
483  call assert_true(&buftype == 'help')
484  call assert_true(winnr() == 1)
485  call assert_true(winnr('$') == 2)
486
487  " This wipes out the buffer, make sure that doesn't cause trouble.
488  Xclose
489
490  new | only
491
492  " Search for non existing help string
493  call assert_fails('Xhelpgrep a1b2c3', 'E480:')
494endfunc
495
496func Test_helpgrep()
497  call s:test_xhelpgrep('c')
498  helpclose
499  call s:test_xhelpgrep('l')
500endfunc
501
502func Test_errortitle()
503  augroup QfBufWinEnter
504    au!
505    au BufWinEnter * :let g:a=get(w:, 'quickfix_title', 'NONE')
506  augroup END
507  copen
508  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'')'}]
509  call setqflist(a)
510  call assert_equal(':setqflist()', g:a)
511  augroup QfBufWinEnter
512    au!
513  augroup END
514  augroup! QfBufWinEnter
515endfunc
516
517func Test_vimgreptitle()
518  augroup QfBufWinEnter
519    au!
520    au BufWinEnter * :let g:a=get(w:, 'quickfix_title', 'NONE')
521  augroup END
522  try
523    vimgrep /pattern/j file
524  catch /E480/
525  endtry
526  copen
527  call assert_equal(':    vimgrep /pattern/j file', g:a)
528  augroup QfBufWinEnter
529    au!
530  augroup END
531  augroup! QfBufWinEnter
532endfunc
533
534func XqfTitleTests(cchar)
535  call s:setup_commands(a:cchar)
536
537  Xgetexpr ['file:1:1:message']
538  let l = g:Xgetlist()
539  if a:cchar == 'c'
540    call setqflist(l, 'r')
541  else
542    call setloclist(0, l, 'r')
543  endif
544
545  Xopen
546  if a:cchar == 'c'
547    let title = ':setqflist()'
548  else
549    let title = ':setloclist()'
550  endif
551  call assert_equal(title, w:quickfix_title)
552  Xclose
553endfunc
554
555" Tests for quickfix window's title
556func Test_qf_title()
557  call XqfTitleTests('c')
558  call XqfTitleTests('l')
559endfunc
560
561" Tests for 'errorformat'
562func Test_efm()
563  let save_efm = &efm
564  set efm=%EEEE%m,%WWWW%m,%+CCCC%.%#,%-GGGG%.%#
565  cgetexpr ['WWWW', 'EEEE', 'CCCC']
566  let l = strtrans(string(map(getqflist(), '[v:val.text, v:val.valid]')))
567  call assert_equal("[['W', 1], ['E^@CCCC', 1]]", l)
568  cgetexpr ['WWWW', 'GGGG', 'EEEE', 'CCCC']
569  let l = strtrans(string(map(getqflist(), '[v:val.text, v:val.valid]')))
570  call assert_equal("[['W', 1], ['E^@CCCC', 1]]", l)
571  cgetexpr ['WWWW', 'GGGG', 'ZZZZ', 'EEEE', 'CCCC', 'YYYY']
572  let l = strtrans(string(map(getqflist(), '[v:val.text, v:val.valid]')))
573  call assert_equal("[['W', 1], ['ZZZZ', 0], ['E^@CCCC', 1], ['YYYY', 0]]", l)
574  let &efm = save_efm
575endfunc
576
577" This will test for problems in quickfix:
578" A. incorrectly copying location lists which caused the location list to show
579"    a different name than the file that was actually being displayed.
580" B. not reusing the window for which the location list window is opened but
581"    instead creating new windows.
582" C. make sure that the location list window is not reused instead of the
583"    window it belongs to.
584"
585" Set up the test environment:
586func ReadTestProtocol(name)
587  let base = substitute(a:name, '\v^test://(.*)%(\.[^.]+)?', '\1', '')
588  let word = substitute(base, '\v(.*)\..*', '\1', '')
589
590  setl modifiable
591  setl noreadonly
592  setl noswapfile
593  setl bufhidden=delete
594  %del _
595  " For problem 2:
596  " 'buftype' has to be set to reproduce the constant opening of new windows
597  setl buftype=nofile
598
599  call setline(1, word)
600
601  setl nomodified
602  setl nomodifiable
603  setl readonly
604  exe 'doautocmd BufRead ' . substitute(a:name, '\v^test://(.*)', '\1', '')
605endfunc
606
607func Test_locationlist()
608    enew
609
610    augroup testgroup
611      au!
612      autocmd BufReadCmd test://* call ReadTestProtocol(expand("<amatch>"))
613    augroup END
614
615    let words = [ "foo", "bar", "baz", "quux", "shmoo", "spam", "eggs" ]
616
617    let qflist = []
618    for word in words
619      call add(qflist, {'filename': 'test://' . word . '.txt', 'text': 'file ' . word . '.txt', })
620      " NOTE: problem 1:
621      " intentionally not setting 'lnum' so that the quickfix entries are not
622      " valid
623      call setloclist(0, qflist, ' ')
624    endfor
625
626    " Test A
627    lrewind
628    enew
629    lopen
630    4lnext
631    vert split
632    wincmd L
633    lopen
634    wincmd p
635    lnext
636    let fileName = expand("%")
637    wincmd p
638    let locationListFileName = substitute(getline(line('.')), '\([^|]*\)|.*', '\1', '')
639    let fileName = substitute(fileName, '\\', '/', 'g')
640    let locationListFileName = substitute(locationListFileName, '\\', '/', 'g')
641    call assert_equal("test://bar.txt", fileName)
642    call assert_equal("test://bar.txt", locationListFileName)
643
644    wincmd n | only
645
646    " Test B:
647    lrewind
648    lopen
649    2
650    exe "normal \<CR>"
651    wincmd p
652    3
653    exe "normal \<CR>"
654    wincmd p
655    4
656    exe "normal \<CR>"
657    call assert_equal(2, winnr('$'))
658    wincmd n | only
659
660    " Test C:
661    lrewind
662    lopen
663    " Let's move the location list window to the top to check whether it (the
664    " first window found) will be reused when we try to open new windows:
665    wincmd K
666    2
667    exe "normal \<CR>"
668    wincmd p
669    3
670    exe "normal \<CR>"
671    wincmd p
672    4
673    exe "normal \<CR>"
674    1wincmd w
675    call assert_equal('quickfix', &buftype)
676    2wincmd w
677    let bufferName = expand("%")
678    let bufferName = substitute(bufferName, '\\', '/', 'g')
679    call assert_equal('test://quux.txt', bufferName)
680
681    wincmd n | only
682
683    augroup! testgroup
684endfunc
685
686func Test_locationlist_curwin_was_closed()
687    augroup testgroup
688      au!
689      autocmd BufReadCmd test_curwin.txt call R(expand("<amatch>"))
690    augroup END
691
692    func! R(n)
693      quit
694    endfunc
695
696    new
697    let q = []
698    call add(q, {'filename': 'test_curwin.txt' })
699    call setloclist(0, q)
700    call assert_fails('lrewind', 'E924:')
701
702    augroup! testgroup
703endfunc
704
705func Test_locationlist_cross_tab_jump()
706  call writefile(['loclistfoo'], 'loclistfoo')
707  call writefile(['loclistbar'], 'loclistbar')
708  set switchbuf=usetab
709
710  edit loclistfoo
711  tabedit loclistbar
712  silent lgrep loclistfoo loclist*
713  call assert_equal(1, tabpagenr())
714
715  enew | only | tabonly
716  set switchbuf&vim
717  call delete('loclistfoo')
718  call delete('loclistbar')
719endfunc
720
721" More tests for 'errorformat'
722func Test_efm1()
723    if !has('unix')
724	" The 'errorformat' setting is different on non-Unix systems.
725	" This test works only on Unix-like systems.
726	return
727    endif
728
729    let l = [
730      \ '"Xtestfile", line 4.12: 1506-045 (S) Undeclared identifier fd_set.',
731      \ '"Xtestfile", line 6 col 19; this is an error',
732      \ 'gcc -c -DHAVE_CONFIsing-prototypes -I/usr/X11R6/include  version.c',
733      \ 'Xtestfile:9: parse error before `asd''',
734      \ 'make: *** [vim] Error 1',
735      \ 'in file "Xtestfile" linenr 10: there is an error',
736      \ '',
737      \ '2 returned',
738      \ '"Xtestfile", line 11 col 1; this is an error',
739      \ '"Xtestfile", line 12 col 2; this is another error',
740      \ '"Xtestfile", line 14:10; this is an error in column 10',
741      \ '=Xtestfile=, line 15:10; this is another error, but in vcol 10 this time',
742      \ '"Xtestfile", linenr 16: yet another problem',
743      \ 'Error in "Xtestfile" at line 17:',
744      \ 'x should be a dot',
745      \ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 17',
746      \ '            ^',
747      \ 'Error in "Xtestfile" at line 18:',
748      \ 'x should be a dot',
749      \ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 18',
750      \ '.............^',
751      \ 'Error in "Xtestfile" at line 19:',
752      \ 'x should be a dot',
753      \ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 19',
754      \ '--------------^',
755      \ 'Error in "Xtestfile" at line 20:',
756      \ 'x should be a dot',
757      \ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 20',
758      \ '	       ^',
759      \ '',
760      \ 'Does anyone know what is the problem and how to correction it?',
761      \ '"Xtestfile", line 21 col 9: What is the title of the quickfix window?',
762      \ '"Xtestfile", line 22 col 9: What is the title of the quickfix window?'
763      \ ]
764
765    call writefile(l, 'Xerrorfile1')
766    call writefile(l[:-2], 'Xerrorfile2')
767
768    let m = [
769	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  2',
770	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  3',
771	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  4',
772	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  5',
773	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  6',
774	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  7',
775	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  8',
776	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  9',
777	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 10',
778	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 11',
779	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 12',
780	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 13',
781	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 14',
782	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 15',
783	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 16',
784	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 17',
785	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 18',
786	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 19',
787	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 20',
788	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 21',
789	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 22'
790	\ ]
791    call writefile(m, 'Xtestfile')
792
793    let save_efm = &efm
794    set efm+==%f=\\,\ line\ %l%*\\D%v%*[^\ ]\ %m
795    set efm^=%AError\ in\ \"%f\"\ at\ line\ %l:,%Z%p^,%C%m
796
797    exe 'cf Xerrorfile2'
798    clast
799    copen
800    call assert_equal(':cf Xerrorfile2', w:quickfix_title)
801    wincmd p
802
803    exe 'cf Xerrorfile1'
804    call assert_equal([4, 12], [line('.'), col('.')])
805    cn
806    call assert_equal([6, 19], [line('.'), col('.')])
807    cn
808    call assert_equal([9, 2], [line('.'), col('.')])
809    cn
810    call assert_equal([10, 2], [line('.'), col('.')])
811    cn
812    call assert_equal([11, 1], [line('.'), col('.')])
813    cn
814    call assert_equal([12, 2], [line('.'), col('.')])
815    cn
816    call assert_equal([14, 10], [line('.'), col('.')])
817    cn
818    call assert_equal([15, 3, 10], [line('.'), col('.'), virtcol('.')])
819    cn
820    call assert_equal([16, 2], [line('.'), col('.')])
821    cn
822    call assert_equal([17, 6], [line('.'), col('.')])
823    cn
824    call assert_equal([18, 7], [line('.'), col('.')])
825    cn
826    call assert_equal([19, 8], [line('.'), col('.')])
827    cn
828    call assert_equal([20, 9], [line('.'), col('.')])
829    clast
830    cprev
831    cprev
832    wincmd w
833    call assert_equal(':cf Xerrorfile1', w:quickfix_title)
834    wincmd p
835
836    let &efm = save_efm
837    call delete('Xerrorfile1')
838    call delete('Xerrorfile2')
839    call delete('Xtestfile')
840endfunc
841
842" Test for quickfix directory stack support
843func s:dir_stack_tests(cchar)
844  call s:setup_commands(a:cchar)
845
846  let save_efm=&efm
847  set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f'
848
849  let lines = ["Entering dir 'dir1/a'",
850		\ 'habits2.txt:1:Nine Healthy Habits',
851		\ "Entering dir 'b'",
852		\ 'habits3.txt:2:0 Hours of television',
853		\ 'habits2.txt:7:5 Small meals',
854		\ "Entering dir 'dir1/c'",
855		\ 'habits4.txt:3:1 Hour of exercise',
856		\ "Leaving dir 'dir1/c'",
857		\ "Leaving dir 'dir1/a'",
858		\ 'habits1.txt:4:2 Liters of water',
859		\ "Entering dir 'dir2'",
860		\ 'habits5.txt:5:3 Cups of hot green tea',
861		\ "Leaving dir 'dir2'"
862		\]
863
864  Xexpr ""
865  for l in lines
866      Xaddexpr l
867  endfor
868
869  let qf = g:Xgetlist()
870
871  call assert_equal('dir1/a/habits2.txt', bufname(qf[1].bufnr))
872  call assert_equal(1, qf[1].lnum)
873  call assert_equal('dir1/a/b/habits3.txt', bufname(qf[3].bufnr))
874  call assert_equal(2, qf[3].lnum)
875  call assert_equal('dir1/a/habits2.txt', bufname(qf[4].bufnr))
876  call assert_equal(7, qf[4].lnum)
877  call assert_equal('dir1/c/habits4.txt', bufname(qf[6].bufnr))
878  call assert_equal(3, qf[6].lnum)
879  call assert_equal('habits1.txt', bufname(qf[9].bufnr))
880  call assert_equal(4, qf[9].lnum)
881  call assert_equal('dir2/habits5.txt', bufname(qf[11].bufnr))
882  call assert_equal(5, qf[11].lnum)
883
884  let &efm=save_efm
885endfunc
886
887" Tests for %D and %X errorformat options
888func Test_efm_dirstack()
889  " Create the directory stack and files
890  call mkdir('dir1')
891  call mkdir('dir1/a')
892  call mkdir('dir1/a/b')
893  call mkdir('dir1/c')
894  call mkdir('dir2')
895
896  let lines = ["Nine Healthy Habits",
897		\ "0 Hours of television",
898		\ "1 Hour of exercise",
899		\ "2 Liters of water",
900		\ "3 Cups of hot green tea",
901		\ "4 Short mental breaks",
902		\ "5 Small meals",
903		\ "6 AM wake up time",
904		\ "7 Minutes of laughter",
905		\ "8 Hours of sleep (at least)",
906		\ "9 PM end of the day and off to bed"
907		\ ]
908  call writefile(lines, 'habits1.txt')
909  call writefile(lines, 'dir1/a/habits2.txt')
910  call writefile(lines, 'dir1/a/b/habits3.txt')
911  call writefile(lines, 'dir1/c/habits4.txt')
912  call writefile(lines, 'dir2/habits5.txt')
913
914  call s:dir_stack_tests('c')
915  call s:dir_stack_tests('l')
916
917  call delete('dir1', 'rf')
918  call delete('dir2', 'rf')
919  call delete('habits1.txt')
920endfunc
921
922" Test for resync after continuing an ignored message
923func Xefm_ignore_continuations(cchar)
924  call s:setup_commands(a:cchar)
925
926  let save_efm = &efm
927
928  let &efm =
929	\ '%Eerror %m %l,' .
930	\ '%-Wignored %m %l,' .
931	\ '%+Cmore ignored %m %l,' .
932	\ '%Zignored end'
933  Xgetexpr ['ignored warning 1', 'more ignored continuation 2', 'ignored end', 'error resync 4']
934  let l = map(g:Xgetlist(), '[v:val.text, v:val.valid, v:val.lnum, v:val.type]')
935  call assert_equal([['resync', 1, 4, 'E']], l)
936
937  let &efm = save_efm
938endfunc
939
940func Test_efm_ignore_continuations()
941  call Xefm_ignore_continuations('c')
942  call Xefm_ignore_continuations('l')
943endfunc
944
945" Tests for invalid error format specifies
946func Xinvalid_efm_Tests(cchar)
947  call s:setup_commands(a:cchar)
948
949  let save_efm = &efm
950
951  set efm=%f:%l:%m,%f:%f:%l:%m
952  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E372:')
953
954  set efm=%f:%l:%m,%f:%l:%r:%m
955  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E373:')
956
957  set efm=%f:%l:%m,%O:%f:%l:%m
958  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E373:')
959
960  set efm=%f:%l:%m,%f:%l:%*[^a-z
961  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E374:')
962
963  set efm=%f:%l:%m,%f:%l:%*c
964  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E375:')
965
966  set efm=%f:%l:%m,%L%M%N
967  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E376:')
968
969  set efm=%f:%l:%m,%f:%l:%m:%R
970  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E377:')
971
972  set efm=
973  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E378:')
974
975  set efm=%DEntering\ dir\ abc,%f:%l:%m
976  call assert_fails('Xexpr ["Entering dir abc", "abc.txt:1:Hello world"]', 'E379:')
977
978  let &efm = save_efm
979endfunc
980
981func Test_invalid_efm()
982  call Xinvalid_efm_Tests('c')
983  call Xinvalid_efm_Tests('l')
984endfunc
985
986" TODO:
987" Add tests for the following formats in 'errorformat'
988"	%r  %O
989func Test_efm2()
990  let save_efm = &efm
991
992  " Test for %s format in efm
993  set efm=%f:%s
994  cexpr 'Xtestfile:Line search text'
995  let l = getqflist()
996  call assert_equal(l[0].pattern, '^\VLine search text\$')
997  call assert_equal(l[0].lnum, 0)
998
999  let l = split(execute('clist', ''), "\n")
1000  call assert_equal([' 1 Xtestfile:^\VLine search text\$:  '], l)
1001
1002  " Test for %P, %Q and %t format specifiers
1003  let lines=["[Xtestfile1]",
1004	      \ "(1,17)  error: ';' missing",
1005	      \ "(21,2)  warning: variable 'z' not defined",
1006	      \ "(67,3)  error: end of file found before string ended",
1007	      \ "--",
1008	      \ "",
1009	      \ "[Xtestfile2]",
1010	      \ "--",
1011	      \ "",
1012	      \ "[Xtestfile3]",
1013	      \ "NEW compiler v1.1",
1014	      \ "(2,2)   warning: variable 'x' not defined",
1015	      \ "(67,3)  warning: 's' already defined",
1016	      \ "--"
1017	      \]
1018  set efm=%+P[%f]%r,(%l\\,%c)%*[\ ]%t%*[^:]:\ %m,%+Q--%r
1019  " To exercise the push/pop file functionality in quickfix, the test files
1020  " need to be created.
1021  call writefile(['Line1'], 'Xtestfile1')
1022  call writefile(['Line2'], 'Xtestfile2')
1023  call writefile(['Line3'], 'Xtestfile3')
1024  cexpr ""
1025  for l in lines
1026      caddexpr l
1027  endfor
1028  let l = getqflist()
1029  call assert_equal(12, len(l))
1030  call assert_equal(21, l[2].lnum)
1031  call assert_equal(2, l[2].col)
1032  call assert_equal('w', l[2].type)
1033  call assert_equal('e', l[3].type)
1034  call delete('Xtestfile1')
1035  call delete('Xtestfile2')
1036  call delete('Xtestfile3')
1037
1038  " Tests for %E, %C and %Z format specifiers
1039  let lines = ["Error 275",
1040	      \ "line 42",
1041	      \ "column 3",
1042	      \ "' ' expected after '--'"
1043	      \]
1044  set efm=%EError\ %n,%Cline\ %l,%Ccolumn\ %c,%Z%m
1045  cgetexpr lines
1046  let l = getqflist()
1047  call assert_equal(275, l[0].nr)
1048  call assert_equal(42, l[0].lnum)
1049  call assert_equal(3, l[0].col)
1050  call assert_equal('E', l[0].type)
1051  call assert_equal("\n' ' expected after '--'", l[0].text)
1052
1053  " Test for %>
1054  let lines = ["Error in line 147 of foo.c:",
1055	      \"unknown variable 'i'"
1056	      \]
1057  set efm=unknown\ variable\ %m,%E%>Error\ in\ line\ %l\ of\ %f:,%Z%m
1058  cgetexpr lines
1059  let l = getqflist()
1060  call assert_equal(147, l[0].lnum)
1061  call assert_equal('E', l[0].type)
1062  call assert_equal("\nunknown variable 'i'", l[0].text)
1063
1064  " Test for %A, %C and other formats
1065  let lines = [
1066	  \"==============================================================",
1067	  \"FAIL: testGetTypeIdCachesResult (dbfacadeTest.DjsDBFacadeTest)",
1068	  \"--------------------------------------------------------------",
1069	  \"Traceback (most recent call last):",
1070	  \'  File "unittests/dbfacadeTest.py", line 89, in testFoo',
1071	  \"    self.assertEquals(34, dtid)",
1072	  \'  File "/usr/lib/python2.2/unittest.py", line 286, in',
1073	  \" failUnlessEqual",
1074	  \"    raise self.failureException, \\",
1075	  \"AssertionError: 34 != 33",
1076	  \"",
1077	  \"--------------------------------------------------------------",
1078	  \"Ran 27 tests in 0.063s"
1079	  \]
1080  set efm=%C\ %.%#,%A\ \ File\ \"%f\"\\,\ line\ %l%.%#,%Z%[%^\ ]%\\@=%m
1081  cgetexpr lines
1082  let l = getqflist()
1083  call assert_equal(8, len(l))
1084  call assert_equal(89, l[4].lnum)
1085  call assert_equal(1, l[4].valid)
1086  call assert_equal('unittests/dbfacadeTest.py', bufname(l[4].bufnr))
1087
1088  " The following sequence of commands used to crash Vim
1089  set efm=%W%m
1090  cgetexpr ['msg1']
1091  let l = getqflist()
1092  call assert_equal(1, len(l), string(l))
1093  call assert_equal('msg1', l[0].text)
1094  set efm=%C%m
1095  lexpr 'msg2'
1096  let l = getloclist(0)
1097  call assert_equal(1, len(l), string(l))
1098  call assert_equal('msg2', l[0].text)
1099  lopen
1100  call setqflist([], 'r')
1101  caddbuf
1102  let l = getqflist()
1103  call assert_equal(1, len(l), string(l))
1104  call assert_equal('|| msg2', l[0].text)
1105
1106  new | only
1107  let &efm = save_efm
1108endfunc
1109
1110func XquickfixChangedByAutocmd(cchar)
1111  call s:setup_commands(a:cchar)
1112  if a:cchar == 'c'
1113    let ErrorNr = 'E925'
1114    func! ReadFunc()
1115      colder
1116      cgetexpr []
1117    endfunc
1118  else
1119    let ErrorNr = 'E926'
1120    func! ReadFunc()
1121      lolder
1122      lgetexpr []
1123    endfunc
1124  endif
1125
1126  augroup testgroup
1127    au!
1128    autocmd BufReadCmd test_changed.txt call ReadFunc()
1129  augroup END
1130
1131  new | only
1132  let words = [ "a", "b" ]
1133  let qflist = []
1134  for word in words
1135    call add(qflist, {'filename': 'test_changed.txt'})
1136    call g:Xsetlist(qflist, ' ')
1137  endfor
1138  call assert_fails('Xrewind', ErrorNr . ':')
1139
1140  augroup! testgroup
1141endfunc
1142
1143func Test_quickfix_was_changed_by_autocmd()
1144  call XquickfixChangedByAutocmd('c')
1145  call XquickfixChangedByAutocmd('l')
1146endfunc
1147
1148func Test_caddbuffer_to_empty()
1149  helpgr quickfix
1150  call setqflist([], 'r')
1151  cad
1152  try
1153    cn
1154  catch
1155    " number of matches is unknown
1156    call assert_true(v:exception =~ 'E553:')
1157  endtry
1158  quit!
1159endfunc
1160
1161func Test_cgetexpr_works()
1162  " this must not crash Vim
1163  cgetexpr [$x]
1164  lgetexpr [$x]
1165endfunc
1166
1167" Tests for the setqflist() and setloclist() functions
1168func SetXlistTests(cchar, bnum)
1169  call s:setup_commands(a:cchar)
1170
1171  call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 1},
1172	      \  {'bufnr': a:bnum, 'lnum': 2}])
1173  let l = g:Xgetlist()
1174  call assert_equal(2, len(l))
1175  call assert_equal(2, l[1].lnum)
1176
1177  Xnext
1178  call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 3}], 'a')
1179  let l = g:Xgetlist()
1180  call assert_equal(3, len(l))
1181  Xnext
1182  call assert_equal(3, line('.'))
1183
1184  " Appending entries to the list should not change the cursor position
1185  " in the quickfix window
1186  Xwindow
1187  1
1188  call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 4},
1189	      \  {'bufnr': a:bnum, 'lnum': 5}], 'a')
1190  call assert_equal(1, line('.'))
1191  close
1192
1193  call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 3},
1194	      \  {'bufnr': a:bnum, 'lnum': 4},
1195	      \  {'bufnr': a:bnum, 'lnum': 5}], 'r')
1196  let l = g:Xgetlist()
1197  call assert_equal(3, len(l))
1198  call assert_equal(5, l[2].lnum)
1199
1200  call g:Xsetlist([])
1201  let l = g:Xgetlist()
1202  call assert_equal(0, len(l))
1203
1204  " Tests for setting the 'valid' flag
1205  call g:Xsetlist([{'bufnr':a:bnum, 'lnum':4, 'valid':0}])
1206  Xwindow
1207  call assert_equal(1, winnr('$'))
1208  let l = g:Xgetlist()
1209  call g:Xsetlist(l)
1210  call assert_equal(0, g:Xgetlist()[0].valid)
1211  call g:Xsetlist([{'text':'Text1', 'valid':1}])
1212  Xwindow
1213  call assert_equal(2, winnr('$'))
1214  Xclose
1215  let save_efm = &efm
1216  set efm=%m
1217  Xgetexpr 'TestMessage'
1218  let l = g:Xgetlist()
1219  call g:Xsetlist(l)
1220  call assert_equal(1, g:Xgetlist()[0].valid)
1221  let &efm = save_efm
1222
1223  " Error cases:
1224  " Refer to a non-existing buffer and pass a non-dictionary type
1225  call assert_fails("call g:Xsetlist([{'bufnr':998, 'lnum':4}," .
1226	      \ " {'bufnr':999, 'lnum':5}])", 'E92:')
1227  call g:Xsetlist([[1, 2,3]])
1228  call assert_equal(0, len(g:Xgetlist()))
1229endfunc
1230
1231func Test_setqflist()
1232  new Xtestfile | only
1233  let bnum = bufnr('%')
1234  call setline(1, range(1,5))
1235
1236  call SetXlistTests('c', bnum)
1237  call SetXlistTests('l', bnum)
1238
1239  enew!
1240  call delete('Xtestfile')
1241endfunc
1242
1243func Xlist_empty_middle(cchar)
1244  call s:setup_commands(a:cchar)
1245
1246  " create three quickfix lists
1247  let @/ = 'Test_'
1248  Xvimgrep // test_quickfix.vim
1249  let testlen = len(g:Xgetlist())
1250  call assert_true(testlen > 0)
1251  Xvimgrep empty test_quickfix.vim
1252  call assert_true(len(g:Xgetlist()) > 0)
1253  Xvimgrep matches test_quickfix.vim
1254  let matchlen = len(g:Xgetlist())
1255  call assert_true(matchlen > 0)
1256  Xolder
1257  " make the middle list empty
1258  call g:Xsetlist([], 'r')
1259  call assert_true(len(g:Xgetlist()) == 0)
1260  Xolder
1261  call assert_equal(testlen, len(g:Xgetlist()))
1262  Xnewer
1263  Xnewer
1264  call assert_equal(matchlen, len(g:Xgetlist()))
1265endfunc
1266
1267func Test_setqflist_empty_middle()
1268  call Xlist_empty_middle('c')
1269  call Xlist_empty_middle('l')
1270endfunc
1271
1272func Xlist_empty_older(cchar)
1273  call s:setup_commands(a:cchar)
1274
1275  " create three quickfix lists
1276  Xvimgrep one test_quickfix.vim
1277  let onelen = len(g:Xgetlist())
1278  call assert_true(onelen > 0)
1279  Xvimgrep two test_quickfix.vim
1280  let twolen = len(g:Xgetlist())
1281  call assert_true(twolen > 0)
1282  Xvimgrep three test_quickfix.vim
1283  let threelen = len(g:Xgetlist())
1284  call assert_true(threelen > 0)
1285  Xolder 2
1286  " make the first list empty, check the others didn't change
1287  call g:Xsetlist([], 'r')
1288  call assert_true(len(g:Xgetlist()) == 0)
1289  Xnewer
1290  call assert_equal(twolen, len(g:Xgetlist()))
1291  Xnewer
1292  call assert_equal(threelen, len(g:Xgetlist()))
1293endfunc
1294
1295func Test_setqflist_empty_older()
1296  call Xlist_empty_older('c')
1297  call Xlist_empty_older('l')
1298endfunc
1299
1300func XquickfixSetListWithAct(cchar)
1301  call s:setup_commands(a:cchar)
1302
1303  let list1 = [{'filename': 'fnameA', 'text': 'A'},
1304          \    {'filename': 'fnameB', 'text': 'B'}]
1305  let list2 = [{'filename': 'fnameC', 'text': 'C'},
1306          \    {'filename': 'fnameD', 'text': 'D'},
1307          \    {'filename': 'fnameE', 'text': 'E'}]
1308
1309  " {action} is unspecified.  Same as specifing ' '.
1310  new | only
1311  silent! Xnewer 99
1312  call g:Xsetlist(list1)
1313  call g:Xsetlist(list2)
1314  let li = g:Xgetlist()
1315  call assert_equal(3, len(li))
1316  call assert_equal('C', li[0]['text'])
1317  call assert_equal('D', li[1]['text'])
1318  call assert_equal('E', li[2]['text'])
1319  silent! Xolder
1320  let li = g:Xgetlist()
1321  call assert_equal(2, len(li))
1322  call assert_equal('A', li[0]['text'])
1323  call assert_equal('B', li[1]['text'])
1324
1325  " {action} is specified ' '.
1326  new | only
1327  silent! Xnewer 99
1328  call g:Xsetlist(list1)
1329  call g:Xsetlist(list2, ' ')
1330  let li = g:Xgetlist()
1331  call assert_equal(3, len(li))
1332  call assert_equal('C', li[0]['text'])
1333  call assert_equal('D', li[1]['text'])
1334  call assert_equal('E', li[2]['text'])
1335  silent! Xolder
1336  let li = g:Xgetlist()
1337  call assert_equal(2, len(li))
1338  call assert_equal('A', li[0]['text'])
1339  call assert_equal('B', li[1]['text'])
1340
1341  " {action} is specified 'a'.
1342  new | only
1343  silent! Xnewer 99
1344  call g:Xsetlist(list1)
1345  call g:Xsetlist(list2, 'a')
1346  let li = g:Xgetlist()
1347  call assert_equal(5, len(li))
1348  call assert_equal('A', li[0]['text'])
1349  call assert_equal('B', li[1]['text'])
1350  call assert_equal('C', li[2]['text'])
1351  call assert_equal('D', li[3]['text'])
1352  call assert_equal('E', li[4]['text'])
1353
1354  " {action} is specified 'r'.
1355  new | only
1356  silent! Xnewer 99
1357  call g:Xsetlist(list1)
1358  call g:Xsetlist(list2, 'r')
1359  let li = g:Xgetlist()
1360  call assert_equal(3, len(li))
1361  call assert_equal('C', li[0]['text'])
1362  call assert_equal('D', li[1]['text'])
1363  call assert_equal('E', li[2]['text'])
1364
1365  " Test for wrong value.
1366  new | only
1367  call assert_fails("call g:Xsetlist(0)", 'E714:')
1368  call assert_fails("call g:Xsetlist(list1, '')", 'E927:')
1369  call assert_fails("call g:Xsetlist(list1, 'aa')", 'E927:')
1370  call assert_fails("call g:Xsetlist(list1, ' a')", 'E927:')
1371  call assert_fails("call g:Xsetlist(list1, 0)", 'E928:')
1372endfunc
1373
1374func Test_quickfix_set_list_with_act()
1375  call XquickfixSetListWithAct('c')
1376  call XquickfixSetListWithAct('l')
1377endfunc
1378
1379func XLongLinesTests(cchar)
1380  let l = g:Xgetlist()
1381
1382  call assert_equal(4, len(l))
1383  call assert_equal(1, l[0].lnum)
1384  call assert_equal(1, l[0].col)
1385  call assert_equal(1975, len(l[0].text))
1386  call assert_equal(2, l[1].lnum)
1387  call assert_equal(1, l[1].col)
1388  call assert_equal(4070, len(l[1].text))
1389  call assert_equal(3, l[2].lnum)
1390  call assert_equal(1, l[2].col)
1391  call assert_equal(4070, len(l[2].text))
1392  call assert_equal(4, l[3].lnum)
1393  call assert_equal(1, l[3].col)
1394  call assert_equal(10, len(l[3].text))
1395
1396  call g:Xsetlist([], 'r')
1397endfunc
1398
1399func s:long_lines_tests(cchar)
1400  call s:setup_commands(a:cchar)
1401
1402  let testfile = 'samples/quickfix.txt'
1403
1404  " file
1405  exe 'Xgetfile' testfile
1406  call XLongLinesTests(a:cchar)
1407
1408  " list
1409  Xexpr readfile(testfile)
1410  call XLongLinesTests(a:cchar)
1411
1412  " string
1413  Xexpr join(readfile(testfile), "\n")
1414  call XLongLinesTests(a:cchar)
1415
1416  " buffer
1417  exe 'edit' testfile
1418  exe 'Xbuffer' bufnr('%')
1419  call XLongLinesTests(a:cchar)
1420endfunc
1421
1422func Test_long_lines()
1423  call s:long_lines_tests('c')
1424  call s:long_lines_tests('l')
1425endfunc
1426
1427func s:create_test_file(filename)
1428  let l = []
1429  for i in range(1, 20)
1430      call add(l, 'Line' . i)
1431  endfor
1432  call writefile(l, a:filename)
1433endfunc
1434
1435func Test_switchbuf()
1436  call s:create_test_file('Xqftestfile1')
1437  call s:create_test_file('Xqftestfile2')
1438  call s:create_test_file('Xqftestfile3')
1439
1440  new | only
1441  edit Xqftestfile1
1442  let file1_winid = win_getid()
1443  new Xqftestfile2
1444  let file2_winid = win_getid()
1445  cgetexpr ['Xqftestfile1:5:Line5',
1446		\ 'Xqftestfile1:6:Line6',
1447		\ 'Xqftestfile2:10:Line10',
1448		\ 'Xqftestfile2:11:Line11',
1449		\ 'Xqftestfile3:15:Line15',
1450		\ 'Xqftestfile3:16:Line16']
1451
1452  new
1453  let winid = win_getid()
1454  cfirst | cnext
1455  call assert_equal(winid, win_getid())
1456  2cnext
1457  call assert_equal(winid, win_getid())
1458  2cnext
1459  call assert_equal(winid, win_getid())
1460  enew
1461
1462  set switchbuf=useopen
1463  cfirst | cnext
1464  call assert_equal(file1_winid, win_getid())
1465  2cnext
1466  call assert_equal(file2_winid, win_getid())
1467  2cnext
1468  call assert_equal(file2_winid, win_getid())
1469
1470  enew | only
1471  set switchbuf=usetab
1472  tabedit Xqftestfile1
1473  tabedit Xqftestfile2
1474  tabfirst
1475  cfirst | cnext
1476  call assert_equal(2, tabpagenr())
1477  2cnext
1478  call assert_equal(3, tabpagenr())
1479  2cnext
1480  call assert_equal(3, tabpagenr())
1481  tabfirst | tabonly | enew
1482
1483  set switchbuf=split
1484  cfirst | cnext
1485  call assert_equal(1, winnr('$'))
1486  cnext | cnext
1487  call assert_equal(2, winnr('$'))
1488  cnext | cnext
1489  call assert_equal(3, winnr('$'))
1490  enew | only
1491
1492  set switchbuf=newtab
1493  cfirst | cnext
1494  call assert_equal(1, tabpagenr('$'))
1495  cnext | cnext
1496  call assert_equal(2, tabpagenr('$'))
1497  cnext | cnext
1498  call assert_equal(3, tabpagenr('$'))
1499  tabfirst | enew | tabonly | only
1500
1501  set switchbuf=
1502  edit Xqftestfile1
1503  let file1_winid = win_getid()
1504  new Xqftestfile2
1505  let file2_winid = win_getid()
1506  copen
1507  exe "normal 1G\<CR>"
1508  call assert_equal(file1_winid, win_getid())
1509  copen
1510  exe "normal 3G\<CR>"
1511  call assert_equal(file2_winid, win_getid())
1512  copen | only
1513  exe "normal 5G\<CR>"
1514  call assert_equal(2, winnr('$'))
1515  call assert_equal(1, bufwinnr('Xqftestfile3'))
1516
1517  " If only quickfix window is open in the current tabpage, jumping to an
1518  " entry with 'switchubf' set to 'usetab' should search in other tabpages.
1519  enew | only
1520  set switchbuf=usetab
1521  tabedit Xqftestfile1
1522  tabedit Xqftestfile2
1523  tabedit Xqftestfile3
1524  tabfirst
1525  copen | only
1526  clast
1527  call assert_equal(4, tabpagenr())
1528  tabfirst | tabonly | enew | only
1529
1530  call delete('Xqftestfile1')
1531  call delete('Xqftestfile2')
1532  call delete('Xqftestfile3')
1533  set switchbuf&vim
1534
1535  enew | only
1536endfunc
1537
1538func Xadjust_qflnum(cchar)
1539  call s:setup_commands(a:cchar)
1540
1541  enew | only
1542
1543  let fname = 'Xqftestfile' . a:cchar
1544  call s:create_test_file(fname)
1545  exe 'edit ' . fname
1546
1547  Xgetexpr [fname . ':5:Line5',
1548	      \ fname . ':10:Line10',
1549	      \ fname . ':15:Line15',
1550	      \ fname . ':20:Line20']
1551
1552  6,14delete
1553  call append(6, ['Buffer', 'Window'])
1554
1555  let l = g:Xgetlist()
1556
1557  call assert_equal(5, l[0].lnum)
1558  call assert_equal(6, l[2].lnum)
1559  call assert_equal(13, l[3].lnum)
1560
1561  enew!
1562  call delete(fname)
1563endfunc
1564
1565func Test_adjust_lnum()
1566  call setloclist(0, [])
1567  call Xadjust_qflnum('c')
1568  call setqflist([])
1569  call Xadjust_qflnum('l')
1570endfunc
1571
1572" Tests for the :grep/:lgrep and :grepadd/:lgrepadd commands
1573func s:test_xgrep(cchar)
1574  call s:setup_commands(a:cchar)
1575
1576  " The following lines are used for the grep test. Don't remove.
1577  " Grep_Test_Text: Match 1
1578  " Grep_Test_Text: Match 2
1579  " GrepAdd_Test_Text: Match 1
1580  " GrepAdd_Test_Text: Match 2
1581  enew! | only
1582  set makeef&vim
1583  silent Xgrep Grep_Test_Text: test_quickfix.vim
1584  call assert_true(len(g:Xgetlist()) == 3)
1585  Xopen
1586  call assert_true(w:quickfix_title =~ '^:grep')
1587  Xclose
1588  enew
1589  set makeef=Temp_File_##
1590  silent Xgrepadd GrepAdd_Test_Text: test_quickfix.vim
1591  call assert_true(len(g:Xgetlist()) == 6)
1592endfunc
1593
1594func Test_grep()
1595  if !has('unix')
1596    " The grepprg may not be set on non-Unix systems
1597    return
1598  endif
1599
1600  call s:test_xgrep('c')
1601  call s:test_xgrep('l')
1602endfunc
1603
1604func Test_two_windows()
1605  " Use one 'errorformat' for two windows.  Add an expression to each of them,
1606  " make sure they each keep their own state.
1607  set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f'
1608  call mkdir('Xone/a', 'p')
1609  call mkdir('Xtwo/a', 'p')
1610  let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7']
1611  call writefile(lines, 'Xone/a/one.txt')
1612  call writefile(lines, 'Xtwo/a/two.txt')
1613
1614  new one
1615  let one_id = win_getid()
1616  lexpr ""
1617  new two
1618  let two_id = win_getid()
1619  lexpr ""
1620
1621  laddexpr "Entering dir 'Xtwo/a'"
1622  call win_gotoid(one_id)
1623  laddexpr "Entering dir 'Xone/a'"
1624  call win_gotoid(two_id)
1625  laddexpr 'two.txt:5:two two two'
1626  call win_gotoid(one_id)
1627  laddexpr 'one.txt:3:one one one'
1628
1629  let loc_one = getloclist(one_id)
1630  call assert_equal('Xone/a/one.txt', bufname(loc_one[1].bufnr))
1631  call assert_equal(3, loc_one[1].lnum)
1632
1633  let loc_two = getloclist(two_id)
1634  call assert_equal('Xtwo/a/two.txt', bufname(loc_two[1].bufnr))
1635  call assert_equal(5, loc_two[1].lnum)
1636
1637  call win_gotoid(one_id)
1638  bwipe!
1639  call win_gotoid(two_id)
1640  bwipe!
1641  call delete('Xone', 'rf')
1642  call delete('Xtwo', 'rf')
1643endfunc
1644
1645func XbottomTests(cchar)
1646  call s:setup_commands(a:cchar)
1647
1648  " Calling lbottom without any errors should fail
1649  if a:cchar == 'l'
1650      call assert_fails('lbottom', 'E776:')
1651  endif
1652
1653  call g:Xsetlist([{'filename': 'foo', 'lnum': 42}])
1654  Xopen
1655  let wid = win_getid()
1656  call assert_equal(1, line('.'))
1657  wincmd w
1658  call g:Xsetlist([{'filename': 'var', 'lnum': 24}], 'a')
1659  Xbottom
1660  call win_gotoid(wid)
1661  call assert_equal(2, line('.'))
1662  Xclose
1663endfunc
1664
1665" Tests for the :cbottom and :lbottom commands
1666func Test_cbottom()
1667  call XbottomTests('c')
1668  call XbottomTests('l')
1669endfunc
1670
1671func HistoryTest(cchar)
1672  call s:setup_commands(a:cchar)
1673
1674  " clear all lists after the first one, then replace the first one.
1675  call g:Xsetlist([])
1676  call assert_fails('Xolder 99', 'E380:')
1677  let entry = {'filename': 'foo', 'lnum': 42}
1678  call g:Xsetlist([entry], 'r')
1679  call g:Xsetlist([entry, entry])
1680  call g:Xsetlist([entry, entry, entry])
1681  let res = split(execute(a:cchar . 'hist'), "\n")
1682  call assert_equal(3, len(res))
1683  let common = 'errors     :set' . (a:cchar == 'c' ? 'qf' : 'loc') . 'list()'
1684  call assert_equal('  error list 1 of 3; 1 ' . common, res[0])
1685  call assert_equal('  error list 2 of 3; 2 ' . common, res[1])
1686  call assert_equal('> error list 3 of 3; 3 ' . common, res[2])
1687endfunc
1688
1689func Test_history()
1690  call HistoryTest('c')
1691  call HistoryTest('l')
1692endfunc
1693
1694func Test_duplicate_buf()
1695  " make sure we can get the highest buffer number
1696  edit DoesNotExist
1697  edit DoesNotExist2
1698  let last_buffer = bufnr("$")
1699
1700  " make sure only one buffer is created
1701  call writefile(['this one', 'that one'], 'Xgrepthis')
1702  vimgrep one Xgrepthis
1703  vimgrep one Xgrepthis
1704  call assert_equal(last_buffer + 1, bufnr("$"))
1705
1706  call delete('Xgrepthis')
1707endfunc
1708
1709" Quickfix/Location list set/get properties tests
1710func Xproperty_tests(cchar)
1711    call s:setup_commands(a:cchar)
1712
1713    " Error cases
1714    call assert_fails('call g:Xgetlist(99)', 'E715:')
1715    call assert_fails('call g:Xsetlist(99)', 'E714:')
1716    call assert_fails('call g:Xsetlist([], "a", [])', 'E715:')
1717
1718    " Set and get the title
1719    call g:Xsetlist([])
1720    Xopen
1721    wincmd p
1722    call g:Xsetlist([{'filename':'foo', 'lnum':27}])
1723    let s = g:Xsetlist([], 'a', {'title' : 'Sample'})
1724    call assert_equal(0, s)
1725    let d = g:Xgetlist({"title":1})
1726    call assert_equal('Sample', d.title)
1727
1728    Xopen
1729    call assert_equal('Sample', w:quickfix_title)
1730    Xclose
1731
1732    " Tests for action argument
1733    silent! Xolder 999
1734    let qfnr = g:Xgetlist({'all':1}).nr
1735    call g:Xsetlist([], 'r', {'title' : 'N1'})
1736    call assert_equal('N1', g:Xgetlist({'all':1}).title)
1737    call g:Xsetlist([], ' ', {'title' : 'N2'})
1738    call assert_equal(qfnr + 1, g:Xgetlist({'all':1}).nr)
1739
1740    let res = g:Xgetlist({'nr': 0})
1741    call assert_equal(qfnr + 1, res.nr)
1742    call assert_equal(['nr'], keys(res))
1743
1744    call g:Xsetlist([], ' ', {'title' : 'N3'})
1745    call assert_equal('N2', g:Xgetlist({'nr':2, 'title':1}).title)
1746
1747    " Changing the title of an earlier quickfix list
1748    call g:Xsetlist([], ' ', {'title' : 'NewTitle', 'nr' : 2})
1749    call assert_equal('NewTitle', g:Xgetlist({'nr':2, 'title':1}).title)
1750
1751    " Changing the title of an invalid quickfix list
1752    call assert_equal(-1, g:Xsetlist([], ' ',
1753		\ {'title' : 'SomeTitle', 'nr' : 99}))
1754    call assert_equal(-1, g:Xsetlist([], ' ',
1755		\ {'title' : 'SomeTitle', 'nr' : 'abc'}))
1756
1757    if a:cchar == 'c'
1758	copen
1759	call assert_equal({'winid':win_getid()}, getqflist({'winid':1}))
1760	cclose
1761    endif
1762
1763    " Invalid arguments
1764    call assert_fails('call g:Xgetlist([])', 'E715')
1765    call assert_fails('call g:Xsetlist([], "a", [])', 'E715')
1766    let s = g:Xsetlist([], 'a', {'abc':1})
1767    call assert_equal(-1, s)
1768
1769    call assert_equal({}, g:Xgetlist({'abc':1}))
1770    call assert_equal({}, g:Xgetlist({'nr':99, 'title':1}))
1771    call assert_equal({}, g:Xgetlist({'nr':[], 'title':1}))
1772
1773    if a:cchar == 'l'
1774	call assert_equal({}, getloclist(99, {'title': 1}))
1775    endif
1776
1777    " Context related tests
1778    let s = g:Xsetlist([], 'a', {'context':[1,2,3]})
1779    call assert_equal(0, s)
1780    call test_garbagecollect_now()
1781    let d = g:Xgetlist({'context':1})
1782    call assert_equal([1,2,3], d.context)
1783    call g:Xsetlist([], 'a', {'context':{'color':'green'}})
1784    let d = g:Xgetlist({'context':1})
1785    call assert_equal({'color':'green'}, d.context)
1786    call g:Xsetlist([], 'a', {'context':"Context info"})
1787    let d = g:Xgetlist({'context':1})
1788    call assert_equal("Context info", d.context)
1789    call g:Xsetlist([], 'a', {'context':246})
1790    let d = g:Xgetlist({'context':1})
1791    call assert_equal(246, d.context)
1792    if a:cchar == 'l'
1793	" Test for copying context across two different location lists
1794	new | only
1795	let w1_id = win_getid()
1796	let l = [1]
1797	call setloclist(0, [], 'a', {'context':l})
1798	new
1799	let w2_id = win_getid()
1800	call add(l, 2)
1801	call assert_equal([1, 2], getloclist(w1_id, {'context':1}).context)
1802	call assert_equal([1, 2], getloclist(w2_id, {'context':1}).context)
1803	unlet! l
1804	call assert_equal([1, 2], getloclist(w2_id, {'context':1}).context)
1805	only
1806	call setloclist(0, [], 'f')
1807	call assert_equal({}, getloclist(0, {'context':1}))
1808    endif
1809
1810    " Test for changing the context of previous quickfix lists
1811    call g:Xsetlist([], 'f')
1812    Xexpr "One"
1813    Xexpr "Two"
1814    Xexpr "Three"
1815    call g:Xsetlist([], ' ', {'context' : [1], 'nr' : 1})
1816    call g:Xsetlist([], ' ', {'context' : [2], 'nr' : 2})
1817    " Also, check for setting the context using quickfix list number zero.
1818    call g:Xsetlist([], ' ', {'context' : [3], 'nr' : 0})
1819    call test_garbagecollect_now()
1820    let l = g:Xgetlist({'nr' : 1, 'context' : 1})
1821    call assert_equal([1], l.context)
1822    let l = g:Xgetlist({'nr' : 2, 'context' : 1})
1823    call assert_equal([2], l.context)
1824    let l = g:Xgetlist({'nr' : 3, 'context' : 1})
1825    call assert_equal([3], l.context)
1826
1827    " Test for changing the context through reference and for garbage
1828    " collection of quickfix context
1829    let l = ["red"]
1830    call g:Xsetlist([], ' ', {'context' : l})
1831    call add(l, "blue")
1832    let x = g:Xgetlist({'context' : 1})
1833    call add(x.context, "green")
1834    call assert_equal(["red", "blue", "green"], l)
1835    call assert_equal(["red", "blue", "green"], x.context)
1836    unlet l
1837    call test_garbagecollect_now()
1838    let m = g:Xgetlist({'context' : 1})
1839    call assert_equal(["red", "blue", "green"], m.context)
1840
1841    " Test for setting/getting items
1842    Xexpr ""
1843    let qfprev = g:Xgetlist({'nr':0})
1844    let s = g:Xsetlist([], ' ', {'title':'Green',
1845		\ 'items' : [{'filename':'F1', 'lnum':10}]})
1846    call assert_equal(0, s)
1847    let qfcur = g:Xgetlist({'nr':0})
1848    call assert_true(qfcur.nr == qfprev.nr + 1)
1849    let l = g:Xgetlist({'items':1})
1850    call assert_equal('F1', bufname(l.items[0].bufnr))
1851    call assert_equal(10, l.items[0].lnum)
1852    call g:Xsetlist([], 'a', {'items' : [{'filename':'F2', 'lnum':20},
1853		\  {'filename':'F2', 'lnum':30}]})
1854    let l = g:Xgetlist({'items':1})
1855    call assert_equal('F2', bufname(l.items[2].bufnr))
1856    call assert_equal(30, l.items[2].lnum)
1857    call g:Xsetlist([], 'r', {'items' : [{'filename':'F3', 'lnum':40}]})
1858    let l = g:Xgetlist({'items':1})
1859    call assert_equal('F3', bufname(l.items[0].bufnr))
1860    call assert_equal(40, l.items[0].lnum)
1861    call g:Xsetlist([], 'r', {'items' : []})
1862    let l = g:Xgetlist({'items':1})
1863    call assert_equal(0, len(l.items))
1864
1865    " Save and restore the quickfix stack
1866    call g:Xsetlist([], 'f')
1867    call assert_equal(0, g:Xgetlist({'nr':'$'}).nr)
1868    Xexpr "File1:10:Line1"
1869    Xexpr "File2:20:Line2"
1870    Xexpr "File3:30:Line3"
1871    let last_qf = g:Xgetlist({'nr':'$'}).nr
1872    call assert_equal(3, last_qf)
1873    let qstack = []
1874    for i in range(1, last_qf)
1875	let qstack = add(qstack, g:Xgetlist({'nr':i, 'all':1}))
1876    endfor
1877    call g:Xsetlist([], 'f')
1878    for i in range(len(qstack))
1879	call g:Xsetlist([], ' ', qstack[i])
1880    endfor
1881    call assert_equal(3, g:Xgetlist({'nr':'$'}).nr)
1882    call assert_equal(10, g:Xgetlist({'nr':1, 'items':1}).items[0].lnum)
1883    call assert_equal(20, g:Xgetlist({'nr':2, 'items':1}).items[0].lnum)
1884    call assert_equal(30, g:Xgetlist({'nr':3, 'items':1}).items[0].lnum)
1885    call g:Xsetlist([], 'f')
1886
1887    " Swap two quickfix lists
1888    Xexpr "File1:10:Line10"
1889    Xexpr "File2:20:Line20"
1890    Xexpr "File3:30:Line30"
1891    call g:Xsetlist([], 'r', {'nr':1,'title':'Colors','context':['Colors']})
1892    call g:Xsetlist([], 'r', {'nr':2,'title':'Fruits','context':['Fruits']})
1893    let l1=g:Xgetlist({'nr':1,'all':1})
1894    let l2=g:Xgetlist({'nr':2,'all':1})
1895    let l1.nr=2
1896    let l2.nr=1
1897    call g:Xsetlist([], 'r', l1)
1898    call g:Xsetlist([], 'r', l2)
1899    let newl1=g:Xgetlist({'nr':1,'all':1})
1900    let newl2=g:Xgetlist({'nr':2,'all':1})
1901    call assert_equal(':Fruits', newl1.title)
1902    call assert_equal(['Fruits'], newl1.context)
1903    call assert_equal('Line20', newl1.items[0].text)
1904    call assert_equal(':Colors', newl2.title)
1905    call assert_equal(['Colors'], newl2.context)
1906    call assert_equal('Line10', newl2.items[0].text)
1907    call g:Xsetlist([], 'f')
1908endfunc
1909
1910func Test_qf_property()
1911    call Xproperty_tests('c')
1912    call Xproperty_tests('l')
1913endfunc
1914
1915" Tests for the QuickFixCmdPre/QuickFixCmdPost autocommands
1916func QfAutoCmdHandler(loc, cmd)
1917  call add(g:acmds, a:loc . a:cmd)
1918endfunc
1919
1920func Test_Autocmd()
1921  autocmd QuickFixCmdPre * call QfAutoCmdHandler('pre', expand('<amatch>'))
1922  autocmd QuickFixCmdPost * call QfAutoCmdHandler('post', expand('<amatch>'))
1923
1924  let g:acmds = []
1925  cexpr "F1:10:Line 10"
1926  caddexpr "F1:20:Line 20"
1927  cgetexpr "F1:30:Line 30"
1928  enew! | call append(0, "F2:10:Line 10")
1929  cbuffer!
1930  enew! | call append(0, "F2:20:Line 20")
1931  cgetbuffer
1932  enew! | call append(0, "F2:30:Line 30")
1933  caddbuffer
1934
1935  let l = ['precexpr',
1936	      \ 'postcexpr',
1937	      \ 'precaddexpr',
1938	      \ 'postcaddexpr',
1939	      \ 'precgetexpr',
1940	      \ 'postcgetexpr',
1941	      \ 'precbuffer',
1942	      \ 'postcbuffer',
1943	      \ 'precgetbuffer',
1944	      \ 'postcgetbuffer',
1945	      \ 'precaddbuffer',
1946	      \ 'postcaddbuffer']
1947  call assert_equal(l, g:acmds)
1948endfunc
1949
1950func Test_Autocmd_Exception()
1951  set efm=%m
1952  lgetexpr '?'
1953
1954  try
1955    call DoesNotExit()
1956  catch
1957    lgetexpr '1'
1958  finally
1959    lgetexpr '1'
1960  endtry
1961
1962  call assert_equal('1', getloclist(0)[0].text)
1963
1964  set efm&vim
1965endfunc
1966
1967func Test_caddbuffer_wrong()
1968  " This used to cause a memory access in freed memory.
1969  let save_efm = &efm
1970  set efm=%EEEE%m,%WWWW,%+CCCC%>%#,%GGGG%.#
1971  cgetexpr ['WWWW', 'EEEE', 'CCCC']
1972  let &efm = save_efm
1973  caddbuffer
1974  bwipe!
1975endfunc
1976
1977func Test_caddexpr_wrong()
1978  " This used to cause a memory access in freed memory.
1979  cbuffer
1980  cbuffer
1981  copen
1982  let save_efm = &efm
1983  set efm=%
1984  call assert_fails('caddexpr ""', 'E376:')
1985  let &efm = save_efm
1986endfunc
1987
1988func Test_dirstack_cleanup()
1989  " This used to cause a memory access in freed memory.
1990  let save_efm = &efm
1991  lexpr '0'
1992  lopen
1993  fun X(c)
1994    let save_efm=&efm
1995    set efm=%D%f
1996    if a:c == 'c'
1997      caddexpr '::'
1998    else
1999      laddexpr ':0:0'
2000    endif
2001    let &efm=save_efm
2002  endfun
2003  call X('c')
2004  call X('l')
2005  call setqflist([], 'r')
2006  caddbuffer
2007  let &efm = save_efm
2008endfunc
2009
2010" Tests for jumping to entries from the location list window and quickfix
2011" window
2012func Test_cwindow_jump()
2013  set efm=%f%%%l%%%m
2014  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2015  lopen | only
2016  lfirst
2017  call assert_true(winnr('$') == 2)
2018  call assert_true(winnr() == 1)
2019  " Location list for the new window should be set
2020  call assert_true(getloclist(0)[2].text == 'Line 30')
2021
2022  " Open a scratch buffer
2023  " Open a new window and create a location list
2024  " Open the location list window and close the other window
2025  " Jump to an entry.
2026  " Should create a new window and jump to the entry. The scrtach buffer
2027  " should not be used.
2028  enew | only
2029  set buftype=nofile
2030  below new
2031  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2032  lopen
2033  2wincmd c
2034  lnext
2035  call assert_true(winnr('$') == 3)
2036  call assert_true(winnr() == 2)
2037
2038  " Open two windows with two different location lists
2039  " Open the location list window and close the previous window
2040  " Jump to an entry in the location list window
2041  " Should open the file in the first window and not set the location list.
2042  enew | only
2043  lgetexpr ["F1%5%Line 5"]
2044  below new
2045  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2046  lopen
2047  2wincmd c
2048  lnext
2049  call assert_true(winnr() == 1)
2050  call assert_true(getloclist(0)[0].text == 'Line 5')
2051
2052  enew | only
2053  cgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2054  copen
2055  cnext
2056  call assert_true(winnr('$') == 2)
2057  call assert_true(winnr() == 1)
2058
2059  enew | only
2060  set efm&vim
2061endfunc
2062
2063func XvimgrepTests(cchar)
2064  call s:setup_commands(a:cchar)
2065
2066  call writefile(['Editor:VIM vim',
2067	      \ 'Editor:Emacs EmAcS',
2068	      \ 'Editor:Notepad NOTEPAD'], 'Xtestfile1')
2069  call writefile(['Linux', 'MacOS', 'MS-Windows'], 'Xtestfile2')
2070
2071  " Error cases
2072  call assert_fails('Xvimgrep /abc *', 'E682:')
2073
2074  let @/=''
2075  call assert_fails('Xvimgrep // *', 'E35:')
2076
2077  call assert_fails('Xvimgrep abc', 'E683:')
2078  call assert_fails('Xvimgrep a1b2c3 Xtestfile1', 'E480:')
2079  call assert_fails('Xvimgrep pat Xa1b2c3', 'E480:')
2080
2081  Xexpr ""
2082  Xvimgrepadd Notepad Xtestfile1
2083  Xvimgrepadd MacOS Xtestfile2
2084  let l = g:Xgetlist()
2085  call assert_equal(2, len(l))
2086  call assert_equal('Editor:Notepad NOTEPAD', l[0].text)
2087
2088  Xvimgrep #\cvim#g Xtestfile?
2089  let l = g:Xgetlist()
2090  call assert_equal(2, len(l))
2091  call assert_equal(8, l[0].col)
2092  call assert_equal(12, l[1].col)
2093
2094  1Xvimgrep ?Editor? Xtestfile*
2095  let l = g:Xgetlist()
2096  call assert_equal(1, len(l))
2097  call assert_equal('Editor:VIM vim', l[0].text)
2098
2099  edit +3 Xtestfile2
2100  Xvimgrep +\cemacs+j Xtestfile1
2101  let l = g:Xgetlist()
2102  call assert_equal('Xtestfile2', bufname(''))
2103  call assert_equal('Editor:Emacs EmAcS', l[0].text)
2104
2105  call delete('Xtestfile1')
2106  call delete('Xtestfile2')
2107endfunc
2108
2109" Tests for the :vimgrep command
2110func Test_vimgrep()
2111  call XvimgrepTests('c')
2112  call XvimgrepTests('l')
2113endfunc
2114
2115func XfreeTests(cchar)
2116  call s:setup_commands(a:cchar)
2117
2118  enew | only
2119
2120  " Deleting the quickfix stack should work even When the current list is
2121  " somewhere in the middle of the stack
2122  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2123  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2124  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2125  Xolder
2126  call g:Xsetlist([], 'f')
2127  call assert_equal(0, len(g:Xgetlist()))
2128
2129  " After deleting the stack, adding a new list should create a stack with a
2130  " single list.
2131  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2132  call assert_equal(1, g:Xgetlist({'all':1}).nr)
2133
2134  " Deleting the stack from a quickfix window should update/clear the
2135  " quickfix/location list window.
2136  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2137  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2138  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2139  Xolder
2140  Xwindow
2141  call g:Xsetlist([], 'f')
2142  call assert_equal(2, winnr('$'))
2143  call assert_equal(1, line('$'))
2144  Xclose
2145
2146  " Deleting the stack from a non-quickfix window should update/clear the
2147  " quickfix/location list window.
2148  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2149  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2150  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2151  Xolder
2152  Xwindow
2153  wincmd p
2154  call g:Xsetlist([], 'f')
2155  call assert_equal(0, len(g:Xgetlist()))
2156  wincmd p
2157  call assert_equal(2, winnr('$'))
2158  call assert_equal(1, line('$'))
2159
2160  " After deleting the location list stack, if the location list window is
2161  " opened, then a new location list should be created. So opening the
2162  " location list window again should not create a new window.
2163  if a:cchar == 'l'
2164      lexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2165      wincmd p
2166      lopen
2167      call assert_equal(2, winnr('$'))
2168  endif
2169  Xclose
2170endfunc
2171
2172" Tests for the quickifx free functionality
2173func Test_qf_free()
2174  call XfreeTests('c')
2175  call XfreeTests('l')
2176endfunc
2177
2178" Test for buffer overflow when parsing lines and adding new entries to
2179" the quickfix list.
2180func Test_bufoverflow()
2181  set efm=%f:%l:%m
2182  cgetexpr ['File1:100:' . repeat('x', 1025)]
2183
2184  set efm=%+GCompiler:\ %.%#,%f:%l:%m
2185  cgetexpr ['Compiler: ' . repeat('a', 1015), 'File1:10:Hello World']
2186
2187  set efm=%DEntering\ directory\ %f,%f:%l:%m
2188  cgetexpr ['Entering directory ' . repeat('a', 1006),
2189	      \ 'File1:10:Hello World']
2190  set efm&vim
2191endfunc
2192
2193" Tests for getting the quickfix stack size
2194func XsizeTests(cchar)
2195  call s:setup_commands(a:cchar)
2196
2197  call g:Xsetlist([], 'f')
2198  call assert_equal(0, g:Xgetlist({'nr':'$'}).nr)
2199  call assert_equal(1, len(g:Xgetlist({'nr':'$', 'all':1})))
2200  call assert_equal(0, len(g:Xgetlist({'nr':0})))
2201
2202  Xexpr "File1:10:Line1"
2203  Xexpr "File2:20:Line2"
2204  Xexpr "File3:30:Line3"
2205  Xolder | Xolder
2206  call assert_equal(3, g:Xgetlist({'nr':'$'}).nr)
2207  call g:Xsetlist([], 'f')
2208
2209  Xexpr "File1:10:Line1"
2210  Xexpr "File2:20:Line2"
2211  Xexpr "File3:30:Line3"
2212  Xolder | Xolder
2213  call g:Xsetlist([], 'a', {'nr':'$', 'title':'Compiler'})
2214  call assert_equal('Compiler', g:Xgetlist({'nr':3, 'all':1}).title)
2215endfunc
2216
2217func Test_Qf_Size()
2218  call XsizeTests('c')
2219  call XsizeTests('l')
2220endfunc
2221
2222func Test_cclose_from_copen()
2223    augroup QF_Test
2224	au!
2225        au FileType qf :call assert_fails(':cclose', 'E788')
2226    augroup END
2227    copen
2228    augroup QF_Test
2229	au!
2230    augroup END
2231    augroup! QF_Test
2232endfunc
2233
2234func Test_cclose_in_autocmd()
2235  " Problem is only triggered if "starting" is zero, so that the OptionsSet
2236  " event will be triggered.
2237  call test_override('starting', 1)
2238  augroup QF_Test
2239    au!
2240    au FileType qf :call assert_fails(':cclose', 'E788')
2241  augroup END
2242  copen
2243  augroup QF_Test
2244    au!
2245  augroup END
2246  augroup! QF_Test
2247  call test_override('starting', 0)
2248endfunc
2249
2250func Test_resize_from_copen()
2251    augroup QF_Test
2252	au!
2253        au FileType qf resize 5
2254    augroup END
2255    try
2256	" This should succeed without any exception.  No other buffers are
2257	" involved in the autocmd.
2258	copen
2259    finally
2260	augroup QF_Test
2261	    au!
2262	augroup END
2263	augroup! QF_Test
2264    endtry
2265endfunc
2266
2267" Tests for the quickfix buffer b:changedtick variable
2268func Xchangedtick_tests(cchar)
2269  call s:setup_commands(a:cchar)
2270
2271  new | only
2272
2273  Xexpr "" | Xexpr "" | Xexpr ""
2274
2275  Xopen
2276  Xolder
2277  Xolder
2278  Xaddexpr "F1:10:Line10"
2279  Xaddexpr "F2:20:Line20"
2280  call g:Xsetlist([{"filename":"F3", "lnum":30, "text":"Line30"}], 'a')
2281  call g:Xsetlist([], 'f')
2282  call assert_equal(8, getbufvar('%', 'changedtick'))
2283  Xclose
2284endfunc
2285
2286func Test_changedtick()
2287    call Xchangedtick_tests('c')
2288    call Xchangedtick_tests('l')
2289endfunc
2290
2291" Open multiple help windows using ":lhelpgrep
2292" This test used to crash Vim
2293func Test_Multi_LL_Help()
2294    new | only
2295    lhelpgrep window
2296    lopen
2297    e#
2298    lhelpgrep buffer
2299    call assert_equal(3, winnr('$'))
2300    call assert_true(len(getloclist(1)) != 0)
2301    call assert_true(len(getloclist(2)) != 0)
2302    new | only
2303endfunc
2304