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    " The following used to crash Vim with address sanitizer
1866    call g:Xsetlist([], 'f')
1867    call g:Xsetlist([], 'a', {'items' : [{'filename':'F1', 'lnum':10}]})
1868    call assert_equal(10, g:Xgetlist({'items':1}).items[0].lnum)
1869
1870    " Save and restore the quickfix stack
1871    call g:Xsetlist([], 'f')
1872    call assert_equal(0, g:Xgetlist({'nr':'$'}).nr)
1873    Xexpr "File1:10:Line1"
1874    Xexpr "File2:20:Line2"
1875    Xexpr "File3:30:Line3"
1876    let last_qf = g:Xgetlist({'nr':'$'}).nr
1877    call assert_equal(3, last_qf)
1878    let qstack = []
1879    for i in range(1, last_qf)
1880	let qstack = add(qstack, g:Xgetlist({'nr':i, 'all':1}))
1881    endfor
1882    call g:Xsetlist([], 'f')
1883    for i in range(len(qstack))
1884	call g:Xsetlist([], ' ', qstack[i])
1885    endfor
1886    call assert_equal(3, g:Xgetlist({'nr':'$'}).nr)
1887    call assert_equal(10, g:Xgetlist({'nr':1, 'items':1}).items[0].lnum)
1888    call assert_equal(20, g:Xgetlist({'nr':2, 'items':1}).items[0].lnum)
1889    call assert_equal(30, g:Xgetlist({'nr':3, 'items':1}).items[0].lnum)
1890    call g:Xsetlist([], 'f')
1891
1892    " Swap two quickfix lists
1893    Xexpr "File1:10:Line10"
1894    Xexpr "File2:20:Line20"
1895    Xexpr "File3:30:Line30"
1896    call g:Xsetlist([], 'r', {'nr':1,'title':'Colors','context':['Colors']})
1897    call g:Xsetlist([], 'r', {'nr':2,'title':'Fruits','context':['Fruits']})
1898    let l1=g:Xgetlist({'nr':1,'all':1})
1899    let l2=g:Xgetlist({'nr':2,'all':1})
1900    let l1.nr=2
1901    let l2.nr=1
1902    call g:Xsetlist([], 'r', l1)
1903    call g:Xsetlist([], 'r', l2)
1904    let newl1=g:Xgetlist({'nr':1,'all':1})
1905    let newl2=g:Xgetlist({'nr':2,'all':1})
1906    call assert_equal(':Fruits', newl1.title)
1907    call assert_equal(['Fruits'], newl1.context)
1908    call assert_equal('Line20', newl1.items[0].text)
1909    call assert_equal(':Colors', newl2.title)
1910    call assert_equal(['Colors'], newl2.context)
1911    call assert_equal('Line10', newl2.items[0].text)
1912    call g:Xsetlist([], 'f')
1913endfunc
1914
1915func Test_qf_property()
1916    call Xproperty_tests('c')
1917    call Xproperty_tests('l')
1918endfunc
1919
1920" Tests for the QuickFixCmdPre/QuickFixCmdPost autocommands
1921func QfAutoCmdHandler(loc, cmd)
1922  call add(g:acmds, a:loc . a:cmd)
1923endfunc
1924
1925func Test_Autocmd()
1926  autocmd QuickFixCmdPre * call QfAutoCmdHandler('pre', expand('<amatch>'))
1927  autocmd QuickFixCmdPost * call QfAutoCmdHandler('post', expand('<amatch>'))
1928
1929  let g:acmds = []
1930  cexpr "F1:10:Line 10"
1931  caddexpr "F1:20:Line 20"
1932  cgetexpr "F1:30:Line 30"
1933  enew! | call append(0, "F2:10:Line 10")
1934  cbuffer!
1935  enew! | call append(0, "F2:20:Line 20")
1936  cgetbuffer
1937  enew! | call append(0, "F2:30:Line 30")
1938  caddbuffer
1939
1940  let l = ['precexpr',
1941	      \ 'postcexpr',
1942	      \ 'precaddexpr',
1943	      \ 'postcaddexpr',
1944	      \ 'precgetexpr',
1945	      \ 'postcgetexpr',
1946	      \ 'precbuffer',
1947	      \ 'postcbuffer',
1948	      \ 'precgetbuffer',
1949	      \ 'postcgetbuffer',
1950	      \ 'precaddbuffer',
1951	      \ 'postcaddbuffer']
1952  call assert_equal(l, g:acmds)
1953endfunc
1954
1955func Test_Autocmd_Exception()
1956  set efm=%m
1957  lgetexpr '?'
1958
1959  try
1960    call DoesNotExit()
1961  catch
1962    lgetexpr '1'
1963  finally
1964    lgetexpr '1'
1965  endtry
1966
1967  call assert_equal('1', getloclist(0)[0].text)
1968
1969  set efm&vim
1970endfunc
1971
1972func Test_caddbuffer_wrong()
1973  " This used to cause a memory access in freed memory.
1974  let save_efm = &efm
1975  set efm=%EEEE%m,%WWWW,%+CCCC%>%#,%GGGG%.#
1976  cgetexpr ['WWWW', 'EEEE', 'CCCC']
1977  let &efm = save_efm
1978  caddbuffer
1979  bwipe!
1980endfunc
1981
1982func Test_caddexpr_wrong()
1983  " This used to cause a memory access in freed memory.
1984  cbuffer
1985  cbuffer
1986  copen
1987  let save_efm = &efm
1988  set efm=%
1989  call assert_fails('caddexpr ""', 'E376:')
1990  let &efm = save_efm
1991endfunc
1992
1993func Test_dirstack_cleanup()
1994  " This used to cause a memory access in freed memory.
1995  let save_efm = &efm
1996  lexpr '0'
1997  lopen
1998  fun X(c)
1999    let save_efm=&efm
2000    set efm=%D%f
2001    if a:c == 'c'
2002      caddexpr '::'
2003    else
2004      laddexpr ':0:0'
2005    endif
2006    let &efm=save_efm
2007  endfun
2008  call X('c')
2009  call X('l')
2010  call setqflist([], 'r')
2011  caddbuffer
2012  let &efm = save_efm
2013endfunc
2014
2015" Tests for jumping to entries from the location list window and quickfix
2016" window
2017func Test_cwindow_jump()
2018  set efm=%f%%%l%%%m
2019  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2020  lopen | only
2021  lfirst
2022  call assert_true(winnr('$') == 2)
2023  call assert_true(winnr() == 1)
2024  " Location list for the new window should be set
2025  call assert_true(getloclist(0)[2].text == 'Line 30')
2026
2027  " Open a scratch buffer
2028  " Open a new window and create a location list
2029  " Open the location list window and close the other window
2030  " Jump to an entry.
2031  " Should create a new window and jump to the entry. The scrtach buffer
2032  " should not be used.
2033  enew | only
2034  set buftype=nofile
2035  below new
2036  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2037  lopen
2038  2wincmd c
2039  lnext
2040  call assert_true(winnr('$') == 3)
2041  call assert_true(winnr() == 2)
2042
2043  " Open two windows with two different location lists
2044  " Open the location list window and close the previous window
2045  " Jump to an entry in the location list window
2046  " Should open the file in the first window and not set the location list.
2047  enew | only
2048  lgetexpr ["F1%5%Line 5"]
2049  below new
2050  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2051  lopen
2052  2wincmd c
2053  lnext
2054  call assert_true(winnr() == 1)
2055  call assert_true(getloclist(0)[0].text == 'Line 5')
2056
2057  enew | only
2058  cgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2059  copen
2060  cnext
2061  call assert_true(winnr('$') == 2)
2062  call assert_true(winnr() == 1)
2063
2064  enew | only
2065  set efm&vim
2066endfunc
2067
2068func XvimgrepTests(cchar)
2069  call s:setup_commands(a:cchar)
2070
2071  call writefile(['Editor:VIM vim',
2072	      \ 'Editor:Emacs EmAcS',
2073	      \ 'Editor:Notepad NOTEPAD'], 'Xtestfile1')
2074  call writefile(['Linux', 'MacOS', 'MS-Windows'], 'Xtestfile2')
2075
2076  " Error cases
2077  call assert_fails('Xvimgrep /abc *', 'E682:')
2078
2079  let @/=''
2080  call assert_fails('Xvimgrep // *', 'E35:')
2081
2082  call assert_fails('Xvimgrep abc', 'E683:')
2083  call assert_fails('Xvimgrep a1b2c3 Xtestfile1', 'E480:')
2084  call assert_fails('Xvimgrep pat Xa1b2c3', 'E480:')
2085
2086  Xexpr ""
2087  Xvimgrepadd Notepad Xtestfile1
2088  Xvimgrepadd MacOS Xtestfile2
2089  let l = g:Xgetlist()
2090  call assert_equal(2, len(l))
2091  call assert_equal('Editor:Notepad NOTEPAD', l[0].text)
2092
2093  Xvimgrep #\cvim#g Xtestfile?
2094  let l = g:Xgetlist()
2095  call assert_equal(2, len(l))
2096  call assert_equal(8, l[0].col)
2097  call assert_equal(12, l[1].col)
2098
2099  1Xvimgrep ?Editor? Xtestfile*
2100  let l = g:Xgetlist()
2101  call assert_equal(1, len(l))
2102  call assert_equal('Editor:VIM vim', l[0].text)
2103
2104  edit +3 Xtestfile2
2105  Xvimgrep +\cemacs+j Xtestfile1
2106  let l = g:Xgetlist()
2107  call assert_equal('Xtestfile2', bufname(''))
2108  call assert_equal('Editor:Emacs EmAcS', l[0].text)
2109
2110  call delete('Xtestfile1')
2111  call delete('Xtestfile2')
2112endfunc
2113
2114" Tests for the :vimgrep command
2115func Test_vimgrep()
2116  call XvimgrepTests('c')
2117  call XvimgrepTests('l')
2118endfunc
2119
2120func XfreeTests(cchar)
2121  call s:setup_commands(a:cchar)
2122
2123  enew | only
2124
2125  " Deleting the quickfix stack should work even When the current list is
2126  " somewhere in the middle of the stack
2127  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2128  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2129  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2130  Xolder
2131  call g:Xsetlist([], 'f')
2132  call assert_equal(0, len(g:Xgetlist()))
2133
2134  " After deleting the stack, adding a new list should create a stack with a
2135  " single list.
2136  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2137  call assert_equal(1, g:Xgetlist({'all':1}).nr)
2138
2139  " Deleting the stack from a quickfix window should update/clear the
2140  " quickfix/location list window.
2141  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2142  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2143  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2144  Xolder
2145  Xwindow
2146  call g:Xsetlist([], 'f')
2147  call assert_equal(2, winnr('$'))
2148  call assert_equal(1, line('$'))
2149  Xclose
2150
2151  " Deleting the stack from a non-quickfix window should update/clear the
2152  " quickfix/location list window.
2153  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2154  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2155  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2156  Xolder
2157  Xwindow
2158  wincmd p
2159  call g:Xsetlist([], 'f')
2160  call assert_equal(0, len(g:Xgetlist()))
2161  wincmd p
2162  call assert_equal(2, winnr('$'))
2163  call assert_equal(1, line('$'))
2164
2165  " After deleting the location list stack, if the location list window is
2166  " opened, then a new location list should be created. So opening the
2167  " location list window again should not create a new window.
2168  if a:cchar == 'l'
2169      lexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2170      wincmd p
2171      lopen
2172      call assert_equal(2, winnr('$'))
2173  endif
2174  Xclose
2175endfunc
2176
2177" Tests for the quickifx free functionality
2178func Test_qf_free()
2179  call XfreeTests('c')
2180  call XfreeTests('l')
2181endfunc
2182
2183" Test for buffer overflow when parsing lines and adding new entries to
2184" the quickfix list.
2185func Test_bufoverflow()
2186  set efm=%f:%l:%m
2187  cgetexpr ['File1:100:' . repeat('x', 1025)]
2188
2189  set efm=%+GCompiler:\ %.%#,%f:%l:%m
2190  cgetexpr ['Compiler: ' . repeat('a', 1015), 'File1:10:Hello World']
2191
2192  set efm=%DEntering\ directory\ %f,%f:%l:%m
2193  cgetexpr ['Entering directory ' . repeat('a', 1006),
2194	      \ 'File1:10:Hello World']
2195  set efm&vim
2196endfunc
2197
2198" Tests for getting the quickfix stack size
2199func XsizeTests(cchar)
2200  call s:setup_commands(a:cchar)
2201
2202  call g:Xsetlist([], 'f')
2203  call assert_equal(0, g:Xgetlist({'nr':'$'}).nr)
2204  call assert_equal(1, len(g:Xgetlist({'nr':'$', 'all':1})))
2205  call assert_equal(0, len(g:Xgetlist({'nr':0})))
2206
2207  Xexpr "File1:10:Line1"
2208  Xexpr "File2:20:Line2"
2209  Xexpr "File3:30:Line3"
2210  Xolder | Xolder
2211  call assert_equal(3, g:Xgetlist({'nr':'$'}).nr)
2212  call g:Xsetlist([], 'f')
2213
2214  Xexpr "File1:10:Line1"
2215  Xexpr "File2:20:Line2"
2216  Xexpr "File3:30:Line3"
2217  Xolder | Xolder
2218  call g:Xsetlist([], 'a', {'nr':'$', 'title':'Compiler'})
2219  call assert_equal('Compiler', g:Xgetlist({'nr':3, 'all':1}).title)
2220endfunc
2221
2222func Test_Qf_Size()
2223  call XsizeTests('c')
2224  call XsizeTests('l')
2225endfunc
2226
2227func Test_cclose_from_copen()
2228    augroup QF_Test
2229	au!
2230        au FileType qf :call assert_fails(':cclose', 'E788')
2231    augroup END
2232    copen
2233    augroup QF_Test
2234	au!
2235    augroup END
2236    augroup! QF_Test
2237endfunc
2238
2239func Test_cclose_in_autocmd()
2240  " Problem is only triggered if "starting" is zero, so that the OptionsSet
2241  " event will be triggered.
2242  call test_override('starting', 1)
2243  augroup QF_Test
2244    au!
2245    au FileType qf :call assert_fails(':cclose', 'E788')
2246  augroup END
2247  copen
2248  augroup QF_Test
2249    au!
2250  augroup END
2251  augroup! QF_Test
2252  call test_override('starting', 0)
2253endfunc
2254
2255func Test_resize_from_copen()
2256    augroup QF_Test
2257	au!
2258        au FileType qf resize 5
2259    augroup END
2260    try
2261	" This should succeed without any exception.  No other buffers are
2262	" involved in the autocmd.
2263	copen
2264    finally
2265	augroup QF_Test
2266	    au!
2267	augroup END
2268	augroup! QF_Test
2269    endtry
2270endfunc
2271
2272" Tests for the quickfix buffer b:changedtick variable
2273func Xchangedtick_tests(cchar)
2274  call s:setup_commands(a:cchar)
2275
2276  new | only
2277
2278  Xexpr "" | Xexpr "" | Xexpr ""
2279
2280  Xopen
2281  Xolder
2282  Xolder
2283  Xaddexpr "F1:10:Line10"
2284  Xaddexpr "F2:20:Line20"
2285  call g:Xsetlist([{"filename":"F3", "lnum":30, "text":"Line30"}], 'a')
2286  call g:Xsetlist([], 'f')
2287  call assert_equal(8, getbufvar('%', 'changedtick'))
2288  Xclose
2289endfunc
2290
2291func Test_changedtick()
2292  call Xchangedtick_tests('c')
2293  call Xchangedtick_tests('l')
2294endfunc
2295
2296" Tests for parsing an expression using setqflist()
2297func Xsetexpr_tests(cchar)
2298  call s:setup_commands(a:cchar)
2299
2300  let t = ["File1:10:Line10", "File1:20:Line20"]
2301  call g:Xsetlist([], ' ', {'text' : t})
2302  call g:Xsetlist([], 'a', {'text' : "File1:30:Line30"})
2303
2304  let l = g:Xgetlist()
2305  call assert_equal(3, len(l))
2306  call assert_equal(20, l[1].lnum)
2307  call assert_equal('Line30', l[2].text)
2308  call g:Xsetlist([], 'r', {'text' : "File2:5:Line5"})
2309  let l = g:Xgetlist()
2310  call assert_equal(1, len(l))
2311  call assert_equal('Line5', l[0].text)
2312  call assert_equal(-1, g:Xsetlist([], 'a', {'text' : 10}))
2313
2314  call g:Xsetlist([], 'f')
2315  " Add entries to multiple lists
2316  call g:Xsetlist([], 'a', {'nr' : 1, 'text' : ["File1:10:Line10"]})
2317  call g:Xsetlist([], 'a', {'nr' : 2, 'text' : ["File2:20:Line20"]})
2318  call g:Xsetlist([], 'a', {'nr' : 1, 'text' : ["File1:15:Line15"]})
2319  call g:Xsetlist([], 'a', {'nr' : 2, 'text' : ["File2:25:Line25"]})
2320  call assert_equal('Line15', g:Xgetlist({'nr':1, 'items':1}).items[1].text)
2321  call assert_equal('Line25', g:Xgetlist({'nr':2, 'items':1}).items[1].text)
2322endfunc
2323
2324func Test_setexpr()
2325  call Xsetexpr_tests('c')
2326  call Xsetexpr_tests('l')
2327endfunc
2328
2329" Tests for per quickfix/location list directory stack
2330func Xmultidirstack_tests(cchar)
2331  call s:setup_commands(a:cchar)
2332
2333  call g:Xsetlist([], 'f')
2334  Xexpr "" | Xexpr ""
2335
2336  call g:Xsetlist([], 'a', {'nr' : 1, 'text' : "Entering dir 'Xone/a'"})
2337  call g:Xsetlist([], 'a', {'nr' : 2, 'text' : "Entering dir 'Xtwo/a'"})
2338  call g:Xsetlist([], 'a', {'nr' : 1, 'text' : "one.txt:3:one one one"})
2339  call g:Xsetlist([], 'a', {'nr' : 2, 'text' : "two.txt:5:two two two"})
2340
2341  let l1 = g:Xgetlist({'nr':1, 'items':1})
2342  let l2 = g:Xgetlist({'nr':2, 'items':1})
2343  call assert_equal('Xone/a/one.txt', bufname(l1.items[1].bufnr))
2344  call assert_equal(3, l1.items[1].lnum)
2345  call assert_equal('Xtwo/a/two.txt', bufname(l2.items[1].bufnr))
2346  call assert_equal(5, l2.items[1].lnum)
2347endfunc
2348
2349func Test_multidirstack()
2350  call mkdir('Xone/a', 'p')
2351  call mkdir('Xtwo/a', 'p')
2352  let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7']
2353  call writefile(lines, 'Xone/a/one.txt')
2354  call writefile(lines, 'Xtwo/a/two.txt')
2355  let save_efm = &efm
2356  set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f'
2357
2358  call Xmultidirstack_tests('c')
2359  call Xmultidirstack_tests('l')
2360
2361  let &efm = save_efm
2362  call delete('Xone', 'rf')
2363  call delete('Xtwo', 'rf')
2364endfunc
2365
2366" Tests for per quickfix/location list file stack
2367func Xmultifilestack_tests(cchar)
2368  call s:setup_commands(a:cchar)
2369
2370  call g:Xsetlist([], 'f')
2371  Xexpr "" | Xexpr ""
2372
2373  call g:Xsetlist([], 'a', {'nr' : 1, 'text' : "[one.txt]"})
2374  call g:Xsetlist([], 'a', {'nr' : 2, 'text' : "[two.txt]"})
2375  call g:Xsetlist([], 'a', {'nr' : 1, 'text' : "(3,5) one one one"})
2376  call g:Xsetlist([], 'a', {'nr' : 2, 'text' : "(5,9) two two two"})
2377
2378  let l1 = g:Xgetlist({'nr':1, 'items':1})
2379  let l2 = g:Xgetlist({'nr':2, 'items':1})
2380  call assert_equal('one.txt', bufname(l1.items[1].bufnr))
2381  call assert_equal(3, l1.items[1].lnum)
2382  call assert_equal('two.txt', bufname(l2.items[1].bufnr))
2383  call assert_equal(5, l2.items[1].lnum)
2384endfunc
2385
2386func Test_multifilestack()
2387  let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7']
2388  call writefile(lines, 'one.txt')
2389  call writefile(lines, 'two.txt')
2390  let save_efm = &efm
2391  set efm=%+P[%f],(%l\\,%c)\ %m,%-Q
2392
2393  call Xmultifilestack_tests('c')
2394  call Xmultifilestack_tests('l')
2395
2396  let &efm = save_efm
2397  call delete('one.txt')
2398  call delete('two.txt')
2399endfunc
2400
2401" Tests for per buffer 'efm' setting
2402func Test_perbuf_efm()
2403  call writefile(["File1-10-Line10"], 'one.txt')
2404  call writefile(["File2#20#Line20"], 'two.txt')
2405  set efm=%f#%l#%m
2406  new | only
2407  new
2408  setlocal efm=%f-%l-%m
2409  cfile one.txt
2410  wincmd w
2411  caddfile two.txt
2412
2413  let l = getqflist()
2414  call assert_equal(10, l[0].lnum)
2415  call assert_equal('Line20', l[1].text)
2416
2417  set efm&
2418  new | only
2419  call delete('one.txt')
2420  call delete('two.txt')
2421endfunc
2422
2423" Open multiple help windows using ":lhelpgrep
2424" This test used to crash Vim
2425func Test_Multi_LL_Help()
2426    new | only
2427    lhelpgrep window
2428    lopen
2429    e#
2430    lhelpgrep buffer
2431    call assert_equal(3, winnr('$'))
2432    call assert_true(len(getloclist(1)) != 0)
2433    call assert_true(len(getloclist(2)) != 0)
2434    new | only
2435endfunc
2436