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=* -count Xolder <mods><count>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=* -count Xolder <mods><count>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': bufnr('%'), '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')
433
434  " Should be able to use next/prev with invalid entries
435  Xexpr ""
436  call assert_equal(0, g:Xgetlist({'idx' : 0}).idx)
437  call assert_equal(0, g:Xgetlist({'size' : 0}).size)
438  Xaddexpr ['foo', 'bar', 'baz', 'quux', 'shmoo']
439  call assert_equal(5, g:Xgetlist({'size' : 0}).size)
440  Xlast
441  call assert_equal(5, g:Xgetlist({'idx' : 0}).idx)
442  Xfirst
443  call assert_equal(1, g:Xgetlist({'idx' : 0}).idx)
444  2Xnext
445  call assert_equal(3, g:Xgetlist({'idx' : 0}).idx)
446endfunc
447
448func Test_browse()
449  call Xtest_browse('c')
450  call Xtest_browse('l')
451endfunc
452
453func Test_nomem()
454  call test_alloc_fail(GetAllocId('qf_dirname_start'), 0, 0)
455  call assert_fails('vimgrep vim runtest.vim', 'E342:')
456
457  call test_alloc_fail(GetAllocId('qf_dirname_now'), 0, 0)
458  call assert_fails('vimgrep vim runtest.vim', 'E342:')
459
460  call test_alloc_fail(GetAllocId('qf_namebuf'), 0, 0)
461  call assert_fails('cfile runtest.vim', 'E342:')
462
463  call test_alloc_fail(GetAllocId('qf_errmsg'), 0, 0)
464  call assert_fails('cfile runtest.vim', 'E342:')
465
466  call test_alloc_fail(GetAllocId('qf_pattern'), 0, 0)
467  call assert_fails('cfile runtest.vim', 'E342:')
468
469endfunc
470
471func s:test_xhelpgrep(cchar)
472  call s:setup_commands(a:cchar)
473  Xhelpgrep quickfix
474  Xopen
475  if a:cchar == 'c'
476    let title_text = ':helpgrep quickfix'
477  else
478    let title_text = ':lhelpgrep quickfix'
479  endif
480  call assert_true(w:quickfix_title =~ title_text, w:quickfix_title)
481
482  " Jumping to a help topic should open the help window
483  only
484  Xnext
485  call assert_true(&buftype == 'help')
486  call assert_true(winnr('$') == 2)
487  " Jumping to the next match should reuse the help window
488  Xnext
489  call assert_true(&buftype == 'help')
490  call assert_true(winnr() == 1)
491  call assert_true(winnr('$') == 2)
492  " Jumping to the next match from the quickfix window should reuse the help
493  " window
494  Xopen
495  Xnext
496  call assert_true(&buftype == 'help')
497  call assert_true(winnr() == 1)
498  call assert_true(winnr('$') == 2)
499
500  " This wipes out the buffer, make sure that doesn't cause trouble.
501  Xclose
502
503  if a:cchar == 'l'
504      " When a help window is present, running :lhelpgrep should reuse the
505      " help window and not the current window
506      new | only
507      call g:Xsetlist([], 'f')
508      help index.txt
509      wincmd w
510      lhelpgrep quickfix
511      call assert_equal(1, winnr())
512      call assert_notequal([], getloclist(1))
513      call assert_equal([], getloclist(2))
514  endif
515
516  new | only
517
518  " Search for non existing help string
519  call assert_fails('Xhelpgrep a1b2c3', 'E480:')
520endfunc
521
522func Test_helpgrep()
523  call s:test_xhelpgrep('c')
524  helpclose
525  call s:test_xhelpgrep('l')
526endfunc
527
528func Test_errortitle()
529  augroup QfBufWinEnter
530    au!
531    au BufWinEnter * :let g:a=get(w:, 'quickfix_title', 'NONE')
532  augroup END
533  copen
534  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'')'}]
535  call setqflist(a)
536  call assert_equal(':setqflist()', g:a)
537  augroup QfBufWinEnter
538    au!
539  augroup END
540  augroup! QfBufWinEnter
541endfunc
542
543func Test_vimgreptitle()
544  augroup QfBufWinEnter
545    au!
546    au BufWinEnter * :let g:a=get(w:, 'quickfix_title', 'NONE')
547  augroup END
548  try
549    vimgrep /pattern/j file
550  catch /E480/
551  endtry
552  copen
553  call assert_equal(':    vimgrep /pattern/j file', g:a)
554  augroup QfBufWinEnter
555    au!
556  augroup END
557  augroup! QfBufWinEnter
558endfunc
559
560func XqfTitleTests(cchar)
561  call s:setup_commands(a:cchar)
562
563  Xgetexpr ['file:1:1:message']
564  let l = g:Xgetlist()
565  if a:cchar == 'c'
566    call setqflist(l, 'r')
567  else
568    call setloclist(0, l, 'r')
569  endif
570
571  Xopen
572  if a:cchar == 'c'
573    let title = ':setqflist()'
574  else
575    let title = ':setloclist()'
576  endif
577  call assert_equal(title, w:quickfix_title)
578  Xclose
579endfunc
580
581" Tests for quickfix window's title
582func Test_qf_title()
583  call XqfTitleTests('c')
584  call XqfTitleTests('l')
585endfunc
586
587" Tests for 'errorformat'
588func Test_efm()
589  let save_efm = &efm
590  set efm=%EEEE%m,%WWWW%m,%+CCCC%.%#,%-GGGG%.%#
591  cgetexpr ['WWWW', 'EEEE', 'CCCC']
592  let l = strtrans(string(map(getqflist(), '[v:val.text, v:val.valid]')))
593  call assert_equal("[['W', 1], ['E^@CCCC', 1]]", l)
594  cgetexpr ['WWWW', 'GGGG', 'EEEE', 'CCCC']
595  let l = strtrans(string(map(getqflist(), '[v:val.text, v:val.valid]')))
596  call assert_equal("[['W', 1], ['E^@CCCC', 1]]", l)
597  cgetexpr ['WWWW', 'GGGG', 'ZZZZ', 'EEEE', 'CCCC', 'YYYY']
598  let l = strtrans(string(map(getqflist(), '[v:val.text, v:val.valid]')))
599  call assert_equal("[['W', 1], ['ZZZZ', 0], ['E^@CCCC', 1], ['YYYY', 0]]", l)
600  let &efm = save_efm
601endfunc
602
603" This will test for problems in quickfix:
604" A. incorrectly copying location lists which caused the location list to show
605"    a different name than the file that was actually being displayed.
606" B. not reusing the window for which the location list window is opened but
607"    instead creating new windows.
608" C. make sure that the location list window is not reused instead of the
609"    window it belongs to.
610"
611" Set up the test environment:
612func ReadTestProtocol(name)
613  let base = substitute(a:name, '\v^test://(.*)%(\.[^.]+)?', '\1', '')
614  let word = substitute(base, '\v(.*)\..*', '\1', '')
615
616  setl modifiable
617  setl noreadonly
618  setl noswapfile
619  setl bufhidden=delete
620  %del _
621  " For problem 2:
622  " 'buftype' has to be set to reproduce the constant opening of new windows
623  setl buftype=nofile
624
625  call setline(1, word)
626
627  setl nomodified
628  setl nomodifiable
629  setl readonly
630  exe 'doautocmd BufRead ' . substitute(a:name, '\v^test://(.*)', '\1', '')
631endfunc
632
633func Test_locationlist()
634    enew
635
636    augroup testgroup
637      au!
638      autocmd BufReadCmd test://* call ReadTestProtocol(expand("<amatch>"))
639    augroup END
640
641    let words = [ "foo", "bar", "baz", "quux", "shmoo", "spam", "eggs" ]
642
643    let qflist = []
644    for word in words
645      call add(qflist, {'filename': 'test://' . word . '.txt', 'text': 'file ' . word . '.txt', })
646      " NOTE: problem 1:
647      " intentionally not setting 'lnum' so that the quickfix entries are not
648      " valid
649      call setloclist(0, qflist, ' ')
650    endfor
651
652    " Test A
653    lrewind
654    enew
655    lopen
656    4lnext
657    vert split
658    wincmd L
659    lopen
660    wincmd p
661    lnext
662    let fileName = expand("%")
663    wincmd p
664    let locationListFileName = substitute(getline(line('.')), '\([^|]*\)|.*', '\1', '')
665    let fileName = substitute(fileName, '\\', '/', 'g')
666    let locationListFileName = substitute(locationListFileName, '\\', '/', 'g')
667    call assert_equal("test://bar.txt", fileName)
668    call assert_equal("test://bar.txt", locationListFileName)
669
670    wincmd n | only
671
672    " Test B:
673    lrewind
674    lopen
675    2
676    exe "normal \<CR>"
677    wincmd p
678    3
679    exe "normal \<CR>"
680    wincmd p
681    4
682    exe "normal \<CR>"
683    call assert_equal(2, winnr('$'))
684    wincmd n | only
685
686    " Test C:
687    lrewind
688    lopen
689    " Let's move the location list window to the top to check whether it (the
690    " first window found) will be reused when we try to open new windows:
691    wincmd K
692    2
693    exe "normal \<CR>"
694    wincmd p
695    3
696    exe "normal \<CR>"
697    wincmd p
698    4
699    exe "normal \<CR>"
700    1wincmd w
701    call assert_equal('quickfix', &buftype)
702    2wincmd w
703    let bufferName = expand("%")
704    let bufferName = substitute(bufferName, '\\', '/', 'g')
705    call assert_equal('test://quux.txt', bufferName)
706
707    wincmd n | only
708
709    augroup! testgroup
710endfunc
711
712func Test_locationlist_curwin_was_closed()
713    augroup testgroup
714      au!
715      autocmd BufReadCmd test_curwin.txt call R(expand("<amatch>"))
716    augroup END
717
718    func! R(n)
719      quit
720    endfunc
721
722    new
723    let q = []
724    call add(q, {'filename': 'test_curwin.txt' })
725    call setloclist(0, q)
726    call assert_fails('lrewind', 'E924:')
727
728    augroup! testgroup
729endfunc
730
731func Test_locationlist_cross_tab_jump()
732  call writefile(['loclistfoo'], 'loclistfoo')
733  call writefile(['loclistbar'], 'loclistbar')
734  set switchbuf=usetab
735
736  edit loclistfoo
737  tabedit loclistbar
738  silent lgrep loclistfoo loclist*
739  call assert_equal(1, tabpagenr())
740
741  enew | only | tabonly
742  set switchbuf&vim
743  call delete('loclistfoo')
744  call delete('loclistbar')
745endfunc
746
747" More tests for 'errorformat'
748func Test_efm1()
749    if !has('unix')
750	" The 'errorformat' setting is different on non-Unix systems.
751	" This test works only on Unix-like systems.
752	return
753    endif
754
755    let l = [
756      \ '"Xtestfile", line 4.12: 1506-045 (S) Undeclared identifier fd_set.',
757      \ '"Xtestfile", line 6 col 19; this is an error',
758      \ 'gcc -c -DHAVE_CONFIsing-prototypes -I/usr/X11R6/include  version.c',
759      \ 'Xtestfile:9: parse error before `asd''',
760      \ 'make: *** [vim] Error 1',
761      \ 'in file "Xtestfile" linenr 10: there is an error',
762      \ '',
763      \ '2 returned',
764      \ '"Xtestfile", line 11 col 1; this is an error',
765      \ '"Xtestfile", line 12 col 2; this is another error',
766      \ '"Xtestfile", line 14:10; this is an error in column 10',
767      \ '=Xtestfile=, line 15:10; this is another error, but in vcol 10 this time',
768      \ '"Xtestfile", linenr 16: yet another problem',
769      \ 'Error in "Xtestfile" at line 17:',
770      \ 'x should be a dot',
771      \ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 17',
772      \ '            ^',
773      \ 'Error in "Xtestfile" at line 18:',
774      \ 'x should be a dot',
775      \ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 18',
776      \ '.............^',
777      \ 'Error in "Xtestfile" at line 19:',
778      \ 'x should be a dot',
779      \ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 19',
780      \ '--------------^',
781      \ 'Error in "Xtestfile" at line 20:',
782      \ 'x should be a dot',
783      \ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 20',
784      \ '	       ^',
785      \ '',
786      \ 'Does anyone know what is the problem and how to correction it?',
787      \ '"Xtestfile", line 21 col 9: What is the title of the quickfix window?',
788      \ '"Xtestfile", line 22 col 9: What is the title of the quickfix window?'
789      \ ]
790
791    call writefile(l, 'Xerrorfile1')
792    call writefile(l[:-2], 'Xerrorfile2')
793
794    let m = [
795	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  2',
796	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  3',
797	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  4',
798	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  5',
799	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  6',
800	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  7',
801	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  8',
802	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  9',
803	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 10',
804	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 11',
805	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 12',
806	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 13',
807	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 14',
808	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 15',
809	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 16',
810	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 17',
811	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 18',
812	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 19',
813	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 20',
814	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 21',
815	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 22'
816	\ ]
817    call writefile(m, 'Xtestfile')
818
819    let save_efm = &efm
820    set efm+==%f=\\,\ line\ %l%*\\D%v%*[^\ ]\ %m
821    set efm^=%AError\ in\ \"%f\"\ at\ line\ %l:,%Z%p^,%C%m
822
823    exe 'cf Xerrorfile2'
824    clast
825    copen
826    call assert_equal(':cf Xerrorfile2', w:quickfix_title)
827    wincmd p
828
829    exe 'cf Xerrorfile1'
830    call assert_equal([4, 12], [line('.'), col('.')])
831    cn
832    call assert_equal([6, 19], [line('.'), col('.')])
833    cn
834    call assert_equal([9, 2], [line('.'), col('.')])
835    cn
836    call assert_equal([10, 2], [line('.'), col('.')])
837    cn
838    call assert_equal([11, 1], [line('.'), col('.')])
839    cn
840    call assert_equal([12, 2], [line('.'), col('.')])
841    cn
842    call assert_equal([14, 10], [line('.'), col('.')])
843    cn
844    call assert_equal([15, 3, 10], [line('.'), col('.'), virtcol('.')])
845    cn
846    call assert_equal([16, 2], [line('.'), col('.')])
847    cn
848    call assert_equal([17, 6], [line('.'), col('.')])
849    cn
850    call assert_equal([18, 7], [line('.'), col('.')])
851    cn
852    call assert_equal([19, 8], [line('.'), col('.')])
853    cn
854    call assert_equal([20, 9], [line('.'), col('.')])
855    clast
856    cprev
857    cprev
858    wincmd w
859    call assert_equal(':cf Xerrorfile1', w:quickfix_title)
860    wincmd p
861
862    let &efm = save_efm
863    call delete('Xerrorfile1')
864    call delete('Xerrorfile2')
865    call delete('Xtestfile')
866endfunc
867
868" Test for quickfix directory stack support
869func s:dir_stack_tests(cchar)
870  call s:setup_commands(a:cchar)
871
872  let save_efm=&efm
873  set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f'
874
875  let lines = ["Entering dir 'dir1/a'",
876		\ 'habits2.txt:1:Nine Healthy Habits',
877		\ "Entering dir 'b'",
878		\ 'habits3.txt:2:0 Hours of television',
879		\ 'habits2.txt:7:5 Small meals',
880		\ "Entering dir 'dir1/c'",
881		\ 'habits4.txt:3:1 Hour of exercise',
882		\ "Leaving dir 'dir1/c'",
883		\ "Leaving dir 'dir1/a'",
884		\ 'habits1.txt:4:2 Liters of water',
885		\ "Entering dir 'dir2'",
886		\ 'habits5.txt:5:3 Cups of hot green tea',
887		\ "Leaving dir 'dir2'"
888		\]
889
890  Xexpr ""
891  for l in lines
892      Xaddexpr l
893  endfor
894
895  let qf = g:Xgetlist()
896
897  call assert_equal('dir1/a/habits2.txt', bufname(qf[1].bufnr))
898  call assert_equal(1, qf[1].lnum)
899  call assert_equal('dir1/a/b/habits3.txt', bufname(qf[3].bufnr))
900  call assert_equal(2, qf[3].lnum)
901  call assert_equal('dir1/a/habits2.txt', bufname(qf[4].bufnr))
902  call assert_equal(7, qf[4].lnum)
903  call assert_equal('dir1/c/habits4.txt', bufname(qf[6].bufnr))
904  call assert_equal(3, qf[6].lnum)
905  call assert_equal('habits1.txt', bufname(qf[9].bufnr))
906  call assert_equal(4, qf[9].lnum)
907  call assert_equal('dir2/habits5.txt', bufname(qf[11].bufnr))
908  call assert_equal(5, qf[11].lnum)
909
910  let &efm=save_efm
911endfunc
912
913" Tests for %D and %X errorformat options
914func Test_efm_dirstack()
915  " Create the directory stack and files
916  call mkdir('dir1')
917  call mkdir('dir1/a')
918  call mkdir('dir1/a/b')
919  call mkdir('dir1/c')
920  call mkdir('dir2')
921
922  let lines = ["Nine Healthy Habits",
923		\ "0 Hours of television",
924		\ "1 Hour of exercise",
925		\ "2 Liters of water",
926		\ "3 Cups of hot green tea",
927		\ "4 Short mental breaks",
928		\ "5 Small meals",
929		\ "6 AM wake up time",
930		\ "7 Minutes of laughter",
931		\ "8 Hours of sleep (at least)",
932		\ "9 PM end of the day and off to bed"
933		\ ]
934  call writefile(lines, 'habits1.txt')
935  call writefile(lines, 'dir1/a/habits2.txt')
936  call writefile(lines, 'dir1/a/b/habits3.txt')
937  call writefile(lines, 'dir1/c/habits4.txt')
938  call writefile(lines, 'dir2/habits5.txt')
939
940  call s:dir_stack_tests('c')
941  call s:dir_stack_tests('l')
942
943  call delete('dir1', 'rf')
944  call delete('dir2', 'rf')
945  call delete('habits1.txt')
946endfunc
947
948" Test for resync after continuing an ignored message
949func Xefm_ignore_continuations(cchar)
950  call s:setup_commands(a:cchar)
951
952  let save_efm = &efm
953
954  let &efm =
955	\ '%Eerror %m %l,' .
956	\ '%-Wignored %m %l,' .
957	\ '%+Cmore ignored %m %l,' .
958	\ '%Zignored end'
959  Xgetexpr ['ignored warning 1', 'more ignored continuation 2', 'ignored end', 'error resync 4']
960  let l = map(g:Xgetlist(), '[v:val.text, v:val.valid, v:val.lnum, v:val.type]')
961  call assert_equal([['resync', 1, 4, 'E']], l)
962
963  let &efm = save_efm
964endfunc
965
966func Test_efm_ignore_continuations()
967  call Xefm_ignore_continuations('c')
968  call Xefm_ignore_continuations('l')
969endfunc
970
971" Tests for invalid error format specifies
972func Xinvalid_efm_Tests(cchar)
973  call s:setup_commands(a:cchar)
974
975  let save_efm = &efm
976
977  set efm=%f:%l:%m,%f:%f:%l:%m
978  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E372:')
979
980  set efm=%f:%l:%m,%f:%l:%r:%m
981  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E373:')
982
983  set efm=%f:%l:%m,%O:%f:%l:%m
984  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E373:')
985
986  set efm=%f:%l:%m,%f:%l:%*[^a-z
987  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E374:')
988
989  set efm=%f:%l:%m,%f:%l:%*c
990  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E375:')
991
992  set efm=%f:%l:%m,%L%M%N
993  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E376:')
994
995  set efm=%f:%l:%m,%f:%l:%m:%R
996  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E377:')
997
998  set efm=
999  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E378:')
1000
1001  set efm=%DEntering\ dir\ abc,%f:%l:%m
1002  call assert_fails('Xexpr ["Entering dir abc", "abc.txt:1:Hello world"]', 'E379:')
1003
1004  let &efm = save_efm
1005endfunc
1006
1007func Test_invalid_efm()
1008  call Xinvalid_efm_Tests('c')
1009  call Xinvalid_efm_Tests('l')
1010endfunc
1011
1012" TODO:
1013" Add tests for the following formats in 'errorformat'
1014"	%r  %O
1015func Test_efm2()
1016  let save_efm = &efm
1017
1018  " Test for %s format in efm
1019  set efm=%f:%s
1020  cexpr 'Xtestfile:Line search text'
1021  let l = getqflist()
1022  call assert_equal(l[0].pattern, '^\VLine search text\$')
1023  call assert_equal(l[0].lnum, 0)
1024
1025  let l = split(execute('clist', ''), "\n")
1026  call assert_equal([' 1 Xtestfile:^\VLine search text\$:  '], l)
1027
1028  " Test for %P, %Q and %t format specifiers
1029  let lines=["[Xtestfile1]",
1030	      \ "(1,17)  error: ';' missing",
1031	      \ "(21,2)  warning: variable 'z' not defined",
1032	      \ "(67,3)  error: end of file found before string ended",
1033	      \ "--",
1034	      \ "",
1035	      \ "[Xtestfile2]",
1036	      \ "--",
1037	      \ "",
1038	      \ "[Xtestfile3]",
1039	      \ "NEW compiler v1.1",
1040	      \ "(2,2)   warning: variable 'x' not defined",
1041	      \ "(67,3)  warning: 's' already defined",
1042	      \ "--"
1043	      \]
1044  set efm=%+P[%f]%r,(%l\\,%c)%*[\ ]%t%*[^:]:\ %m,%+Q--%r
1045  " To exercise the push/pop file functionality in quickfix, the test files
1046  " need to be created.
1047  call writefile(['Line1'], 'Xtestfile1')
1048  call writefile(['Line2'], 'Xtestfile2')
1049  call writefile(['Line3'], 'Xtestfile3')
1050  cexpr ""
1051  for l in lines
1052      caddexpr l
1053  endfor
1054  let l = getqflist()
1055  call assert_equal(12, len(l))
1056  call assert_equal(21, l[2].lnum)
1057  call assert_equal(2, l[2].col)
1058  call assert_equal('w', l[2].type)
1059  call assert_equal('e', l[3].type)
1060  call delete('Xtestfile1')
1061  call delete('Xtestfile2')
1062  call delete('Xtestfile3')
1063
1064  " Tests for %E, %C and %Z format specifiers
1065  let lines = ["Error 275",
1066	      \ "line 42",
1067	      \ "column 3",
1068	      \ "' ' expected after '--'"
1069	      \]
1070  set efm=%EError\ %n,%Cline\ %l,%Ccolumn\ %c,%Z%m
1071  cgetexpr lines
1072  let l = getqflist()
1073  call assert_equal(275, l[0].nr)
1074  call assert_equal(42, l[0].lnum)
1075  call assert_equal(3, l[0].col)
1076  call assert_equal('E', l[0].type)
1077  call assert_equal("\n' ' expected after '--'", l[0].text)
1078
1079  " Test for %>
1080  let lines = ["Error in line 147 of foo.c:",
1081	      \"unknown variable 'i'"
1082	      \]
1083  set efm=unknown\ variable\ %m,%E%>Error\ in\ line\ %l\ of\ %f:,%Z%m
1084  cgetexpr lines
1085  let l = getqflist()
1086  call assert_equal(147, l[0].lnum)
1087  call assert_equal('E', l[0].type)
1088  call assert_equal("\nunknown variable 'i'", l[0].text)
1089
1090  " Test for %A, %C and other formats
1091  let lines = [
1092	  \"==============================================================",
1093	  \"FAIL: testGetTypeIdCachesResult (dbfacadeTest.DjsDBFacadeTest)",
1094	  \"--------------------------------------------------------------",
1095	  \"Traceback (most recent call last):",
1096	  \'  File "unittests/dbfacadeTest.py", line 89, in testFoo',
1097	  \"    self.assertEquals(34, dtid)",
1098	  \'  File "/usr/lib/python2.2/unittest.py", line 286, in',
1099	  \" failUnlessEqual",
1100	  \"    raise self.failureException, \\",
1101	  \"AssertionError: 34 != 33",
1102	  \"",
1103	  \"--------------------------------------------------------------",
1104	  \"Ran 27 tests in 0.063s"
1105	  \]
1106  set efm=%C\ %.%#,%A\ \ File\ \"%f\"\\,\ line\ %l%.%#,%Z%[%^\ ]%\\@=%m
1107  cgetexpr lines
1108  let l = getqflist()
1109  call assert_equal(8, len(l))
1110  call assert_equal(89, l[4].lnum)
1111  call assert_equal(1, l[4].valid)
1112  call assert_equal('unittests/dbfacadeTest.py', bufname(l[4].bufnr))
1113
1114  " The following sequence of commands used to crash Vim
1115  set efm=%W%m
1116  cgetexpr ['msg1']
1117  let l = getqflist()
1118  call assert_equal(1, len(l), string(l))
1119  call assert_equal('msg1', l[0].text)
1120  set efm=%C%m
1121  lexpr 'msg2'
1122  let l = getloclist(0)
1123  call assert_equal(1, len(l), string(l))
1124  call assert_equal('msg2', l[0].text)
1125  lopen
1126  call setqflist([], 'r')
1127  caddbuf
1128  let l = getqflist()
1129  call assert_equal(1, len(l), string(l))
1130  call assert_equal('|| msg2', l[0].text)
1131
1132  new | only
1133  let &efm = save_efm
1134endfunc
1135
1136func XquickfixChangedByAutocmd(cchar)
1137  call s:setup_commands(a:cchar)
1138  if a:cchar == 'c'
1139    let ErrorNr = 'E925'
1140    func! ReadFunc()
1141      colder
1142      cgetexpr []
1143    endfunc
1144  else
1145    let ErrorNr = 'E926'
1146    func! ReadFunc()
1147      lolder
1148      lgetexpr []
1149    endfunc
1150  endif
1151
1152  augroup testgroup
1153    au!
1154    autocmd BufReadCmd test_changed.txt call ReadFunc()
1155  augroup END
1156
1157  new | only
1158  let words = [ "a", "b" ]
1159  let qflist = []
1160  for word in words
1161    call add(qflist, {'filename': 'test_changed.txt'})
1162    call g:Xsetlist(qflist, ' ')
1163  endfor
1164  call assert_fails('Xrewind', ErrorNr . ':')
1165
1166  augroup! testgroup
1167endfunc
1168
1169func Test_quickfix_was_changed_by_autocmd()
1170  call XquickfixChangedByAutocmd('c')
1171  call XquickfixChangedByAutocmd('l')
1172endfunc
1173
1174func Test_caddbuffer_to_empty()
1175  helpgr quickfix
1176  call setqflist([], 'r')
1177  cad
1178  try
1179    cn
1180  catch
1181    " number of matches is unknown
1182    call assert_true(v:exception =~ 'E553:')
1183  endtry
1184  quit!
1185endfunc
1186
1187func Test_cgetexpr_works()
1188  " this must not crash Vim
1189  cgetexpr [$x]
1190  lgetexpr [$x]
1191endfunc
1192
1193" Tests for the setqflist() and setloclist() functions
1194func SetXlistTests(cchar, bnum)
1195  call s:setup_commands(a:cchar)
1196
1197  call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 1},
1198	      \  {'bufnr': a:bnum, 'lnum': 2}])
1199  let l = g:Xgetlist()
1200  call assert_equal(2, len(l))
1201  call assert_equal(2, l[1].lnum)
1202
1203  Xnext
1204  call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 3}], 'a')
1205  let l = g:Xgetlist()
1206  call assert_equal(3, len(l))
1207  Xnext
1208  call assert_equal(3, line('.'))
1209
1210  " Appending entries to the list should not change the cursor position
1211  " in the quickfix window
1212  Xwindow
1213  1
1214  call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 4},
1215	      \  {'bufnr': a:bnum, 'lnum': 5}], 'a')
1216  call assert_equal(1, line('.'))
1217  close
1218
1219  call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 3},
1220	      \  {'bufnr': a:bnum, 'lnum': 4},
1221	      \  {'bufnr': a:bnum, 'lnum': 5}], 'r')
1222  let l = g:Xgetlist()
1223  call assert_equal(3, len(l))
1224  call assert_equal(5, l[2].lnum)
1225
1226  call g:Xsetlist([])
1227  let l = g:Xgetlist()
1228  call assert_equal(0, len(l))
1229
1230  " Tests for setting the 'valid' flag
1231  call g:Xsetlist([{'bufnr':a:bnum, 'lnum':4, 'valid':0}])
1232  Xwindow
1233  call assert_equal(1, winnr('$'))
1234  let l = g:Xgetlist()
1235  call g:Xsetlist(l)
1236  call assert_equal(0, g:Xgetlist()[0].valid)
1237  call g:Xsetlist([{'text':'Text1', 'valid':1}])
1238  Xwindow
1239  call assert_equal(2, winnr('$'))
1240  Xclose
1241  let save_efm = &efm
1242  set efm=%m
1243  Xgetexpr 'TestMessage'
1244  let l = g:Xgetlist()
1245  call g:Xsetlist(l)
1246  call assert_equal(1, g:Xgetlist()[0].valid)
1247  let &efm = save_efm
1248
1249  " Error cases:
1250  " Refer to a non-existing buffer and pass a non-dictionary type
1251  call assert_fails("call g:Xsetlist([{'bufnr':998, 'lnum':4}," .
1252	      \ " {'bufnr':999, 'lnum':5}])", 'E92:')
1253  call g:Xsetlist([[1, 2,3]])
1254  call assert_equal(0, len(g:Xgetlist()))
1255endfunc
1256
1257func Test_setqflist()
1258  new Xtestfile | only
1259  let bnum = bufnr('%')
1260  call setline(1, range(1,5))
1261
1262  call SetXlistTests('c', bnum)
1263  call SetXlistTests('l', bnum)
1264
1265  enew!
1266  call delete('Xtestfile')
1267endfunc
1268
1269func Xlist_empty_middle(cchar)
1270  call s:setup_commands(a:cchar)
1271
1272  " create three quickfix lists
1273  let @/ = 'Test_'
1274  Xvimgrep // test_quickfix.vim
1275  let testlen = len(g:Xgetlist())
1276  call assert_true(testlen > 0)
1277  Xvimgrep empty test_quickfix.vim
1278  call assert_true(len(g:Xgetlist()) > 0)
1279  Xvimgrep matches test_quickfix.vim
1280  let matchlen = len(g:Xgetlist())
1281  call assert_true(matchlen > 0)
1282  Xolder
1283  " make the middle list empty
1284  call g:Xsetlist([], 'r')
1285  call assert_true(len(g:Xgetlist()) == 0)
1286  Xolder
1287  call assert_equal(testlen, len(g:Xgetlist()))
1288  Xnewer
1289  Xnewer
1290  call assert_equal(matchlen, len(g:Xgetlist()))
1291endfunc
1292
1293func Test_setqflist_empty_middle()
1294  call Xlist_empty_middle('c')
1295  call Xlist_empty_middle('l')
1296endfunc
1297
1298func Xlist_empty_older(cchar)
1299  call s:setup_commands(a:cchar)
1300
1301  " create three quickfix lists
1302  Xvimgrep one test_quickfix.vim
1303  let onelen = len(g:Xgetlist())
1304  call assert_true(onelen > 0)
1305  Xvimgrep two test_quickfix.vim
1306  let twolen = len(g:Xgetlist())
1307  call assert_true(twolen > 0)
1308  Xvimgrep three test_quickfix.vim
1309  let threelen = len(g:Xgetlist())
1310  call assert_true(threelen > 0)
1311  Xolder 2
1312  " make the first list empty, check the others didn't change
1313  call g:Xsetlist([], 'r')
1314  call assert_true(len(g:Xgetlist()) == 0)
1315  Xnewer
1316  call assert_equal(twolen, len(g:Xgetlist()))
1317  Xnewer
1318  call assert_equal(threelen, len(g:Xgetlist()))
1319endfunc
1320
1321func Test_setqflist_empty_older()
1322  call Xlist_empty_older('c')
1323  call Xlist_empty_older('l')
1324endfunc
1325
1326func XquickfixSetListWithAct(cchar)
1327  call s:setup_commands(a:cchar)
1328
1329  let list1 = [{'filename': 'fnameA', 'text': 'A'},
1330          \    {'filename': 'fnameB', 'text': 'B'}]
1331  let list2 = [{'filename': 'fnameC', 'text': 'C'},
1332          \    {'filename': 'fnameD', 'text': 'D'},
1333          \    {'filename': 'fnameE', 'text': 'E'}]
1334
1335  " {action} is unspecified.  Same as specifing ' '.
1336  new | only
1337  silent! Xnewer 99
1338  call g:Xsetlist(list1)
1339  call g:Xsetlist(list2)
1340  let li = g:Xgetlist()
1341  call assert_equal(3, len(li))
1342  call assert_equal('C', li[0]['text'])
1343  call assert_equal('D', li[1]['text'])
1344  call assert_equal('E', li[2]['text'])
1345  silent! Xolder
1346  let li = g:Xgetlist()
1347  call assert_equal(2, len(li))
1348  call assert_equal('A', li[0]['text'])
1349  call assert_equal('B', li[1]['text'])
1350
1351  " {action} is specified ' '.
1352  new | only
1353  silent! Xnewer 99
1354  call g:Xsetlist(list1)
1355  call g:Xsetlist(list2, ' ')
1356  let li = g:Xgetlist()
1357  call assert_equal(3, len(li))
1358  call assert_equal('C', li[0]['text'])
1359  call assert_equal('D', li[1]['text'])
1360  call assert_equal('E', li[2]['text'])
1361  silent! Xolder
1362  let li = g:Xgetlist()
1363  call assert_equal(2, len(li))
1364  call assert_equal('A', li[0]['text'])
1365  call assert_equal('B', li[1]['text'])
1366
1367  " {action} is specified 'a'.
1368  new | only
1369  silent! Xnewer 99
1370  call g:Xsetlist(list1)
1371  call g:Xsetlist(list2, 'a')
1372  let li = g:Xgetlist()
1373  call assert_equal(5, len(li))
1374  call assert_equal('A', li[0]['text'])
1375  call assert_equal('B', li[1]['text'])
1376  call assert_equal('C', li[2]['text'])
1377  call assert_equal('D', li[3]['text'])
1378  call assert_equal('E', li[4]['text'])
1379
1380  " {action} is specified 'r'.
1381  new | only
1382  silent! Xnewer 99
1383  call g:Xsetlist(list1)
1384  call g:Xsetlist(list2, 'r')
1385  let li = g:Xgetlist()
1386  call assert_equal(3, len(li))
1387  call assert_equal('C', li[0]['text'])
1388  call assert_equal('D', li[1]['text'])
1389  call assert_equal('E', li[2]['text'])
1390
1391  " Test for wrong value.
1392  new | only
1393  call assert_fails("call g:Xsetlist(0)", 'E714:')
1394  call assert_fails("call g:Xsetlist(list1, '')", 'E927:')
1395  call assert_fails("call g:Xsetlist(list1, 'aa')", 'E927:')
1396  call assert_fails("call g:Xsetlist(list1, ' a')", 'E927:')
1397  call assert_fails("call g:Xsetlist(list1, 0)", 'E928:')
1398endfunc
1399
1400func Test_quickfix_set_list_with_act()
1401  call XquickfixSetListWithAct('c')
1402  call XquickfixSetListWithAct('l')
1403endfunc
1404
1405func XLongLinesTests(cchar)
1406  let l = g:Xgetlist()
1407
1408  call assert_equal(4, len(l))
1409  call assert_equal(1, l[0].lnum)
1410  call assert_equal(1, l[0].col)
1411  call assert_equal(1975, len(l[0].text))
1412  call assert_equal(2, l[1].lnum)
1413  call assert_equal(1, l[1].col)
1414  call assert_equal(4070, len(l[1].text))
1415  call assert_equal(3, l[2].lnum)
1416  call assert_equal(1, l[2].col)
1417  call assert_equal(4070, len(l[2].text))
1418  call assert_equal(4, l[3].lnum)
1419  call assert_equal(1, l[3].col)
1420  call assert_equal(10, len(l[3].text))
1421
1422  call g:Xsetlist([], 'r')
1423endfunc
1424
1425func s:long_lines_tests(cchar)
1426  call s:setup_commands(a:cchar)
1427
1428  let testfile = 'samples/quickfix.txt'
1429
1430  " file
1431  exe 'Xgetfile' testfile
1432  call XLongLinesTests(a:cchar)
1433
1434  " list
1435  Xexpr readfile(testfile)
1436  call XLongLinesTests(a:cchar)
1437
1438  " string
1439  Xexpr join(readfile(testfile), "\n")
1440  call XLongLinesTests(a:cchar)
1441
1442  " buffer
1443  exe 'edit' testfile
1444  exe 'Xbuffer' bufnr('%')
1445  call XLongLinesTests(a:cchar)
1446endfunc
1447
1448func Test_long_lines()
1449  call s:long_lines_tests('c')
1450  call s:long_lines_tests('l')
1451endfunc
1452
1453func s:create_test_file(filename)
1454  let l = []
1455  for i in range(1, 20)
1456      call add(l, 'Line' . i)
1457  endfor
1458  call writefile(l, a:filename)
1459endfunc
1460
1461func Test_switchbuf()
1462  call s:create_test_file('Xqftestfile1')
1463  call s:create_test_file('Xqftestfile2')
1464  call s:create_test_file('Xqftestfile3')
1465
1466  new | only
1467  edit Xqftestfile1
1468  let file1_winid = win_getid()
1469  new Xqftestfile2
1470  let file2_winid = win_getid()
1471  cgetexpr ['Xqftestfile1:5:Line5',
1472		\ 'Xqftestfile1:6:Line6',
1473		\ 'Xqftestfile2:10:Line10',
1474		\ 'Xqftestfile2:11:Line11',
1475		\ 'Xqftestfile3:15:Line15',
1476		\ 'Xqftestfile3:16:Line16']
1477
1478  new
1479  let winid = win_getid()
1480  cfirst | cnext
1481  call assert_equal(winid, win_getid())
1482  2cnext
1483  call assert_equal(winid, win_getid())
1484  2cnext
1485  call assert_equal(winid, win_getid())
1486  enew
1487
1488  set switchbuf=useopen
1489  cfirst | cnext
1490  call assert_equal(file1_winid, win_getid())
1491  2cnext
1492  call assert_equal(file2_winid, win_getid())
1493  2cnext
1494  call assert_equal(file2_winid, win_getid())
1495
1496  enew | only
1497  set switchbuf=usetab
1498  tabedit Xqftestfile1
1499  tabedit Xqftestfile2
1500  tabfirst
1501  cfirst | cnext
1502  call assert_equal(2, tabpagenr())
1503  2cnext
1504  call assert_equal(3, tabpagenr())
1505  2cnext
1506  call assert_equal(3, tabpagenr())
1507  tabfirst | tabonly | enew
1508
1509  set switchbuf=split
1510  cfirst | cnext
1511  call assert_equal(1, winnr('$'))
1512  cnext | cnext
1513  call assert_equal(2, winnr('$'))
1514  cnext | cnext
1515  call assert_equal(3, winnr('$'))
1516  enew | only
1517
1518  set switchbuf=newtab
1519  cfirst | cnext
1520  call assert_equal(1, tabpagenr('$'))
1521  cnext | cnext
1522  call assert_equal(2, tabpagenr('$'))
1523  cnext | cnext
1524  call assert_equal(3, tabpagenr('$'))
1525  tabfirst | enew | tabonly | only
1526
1527  set switchbuf=
1528  edit Xqftestfile1
1529  let file1_winid = win_getid()
1530  new Xqftestfile2
1531  let file2_winid = win_getid()
1532  copen
1533  exe "normal 1G\<CR>"
1534  call assert_equal(file1_winid, win_getid())
1535  copen
1536  exe "normal 3G\<CR>"
1537  call assert_equal(file2_winid, win_getid())
1538  copen | only
1539  exe "normal 5G\<CR>"
1540  call assert_equal(2, winnr('$'))
1541  call assert_equal(1, bufwinnr('Xqftestfile3'))
1542
1543  " If only quickfix window is open in the current tabpage, jumping to an
1544  " entry with 'switchubf' set to 'usetab' should search in other tabpages.
1545  enew | only
1546  set switchbuf=usetab
1547  tabedit Xqftestfile1
1548  tabedit Xqftestfile2
1549  tabedit Xqftestfile3
1550  tabfirst
1551  copen | only
1552  clast
1553  call assert_equal(4, tabpagenr())
1554  tabfirst | tabonly | enew | only
1555
1556  call delete('Xqftestfile1')
1557  call delete('Xqftestfile2')
1558  call delete('Xqftestfile3')
1559  set switchbuf&vim
1560
1561  enew | only
1562endfunc
1563
1564func Xadjust_qflnum(cchar)
1565  call s:setup_commands(a:cchar)
1566
1567  enew | only
1568
1569  let fname = 'Xqftestfile' . a:cchar
1570  call s:create_test_file(fname)
1571  exe 'edit ' . fname
1572
1573  Xgetexpr [fname . ':5:Line5',
1574	      \ fname . ':10:Line10',
1575	      \ fname . ':15:Line15',
1576	      \ fname . ':20:Line20']
1577
1578  6,14delete
1579  call append(6, ['Buffer', 'Window'])
1580
1581  let l = g:Xgetlist()
1582
1583  call assert_equal(5, l[0].lnum)
1584  call assert_equal(6, l[2].lnum)
1585  call assert_equal(13, l[3].lnum)
1586
1587  enew!
1588  call delete(fname)
1589endfunc
1590
1591func Test_adjust_lnum()
1592  call setloclist(0, [])
1593  call Xadjust_qflnum('c')
1594  call setqflist([])
1595  call Xadjust_qflnum('l')
1596endfunc
1597
1598" Tests for the :grep/:lgrep and :grepadd/:lgrepadd commands
1599func s:test_xgrep(cchar)
1600  call s:setup_commands(a:cchar)
1601
1602  " The following lines are used for the grep test. Don't remove.
1603  " Grep_Test_Text: Match 1
1604  " Grep_Test_Text: Match 2
1605  " GrepAdd_Test_Text: Match 1
1606  " GrepAdd_Test_Text: Match 2
1607  enew! | only
1608  set makeef&vim
1609  silent Xgrep Grep_Test_Text: test_quickfix.vim
1610  call assert_true(len(g:Xgetlist()) == 3)
1611  Xopen
1612  call assert_true(w:quickfix_title =~ '^:grep')
1613  Xclose
1614  enew
1615  set makeef=Temp_File_##
1616  silent Xgrepadd GrepAdd_Test_Text: test_quickfix.vim
1617  call assert_true(len(g:Xgetlist()) == 6)
1618endfunc
1619
1620func Test_grep()
1621  if !has('unix')
1622    " The grepprg may not be set on non-Unix systems
1623    return
1624  endif
1625
1626  call s:test_xgrep('c')
1627  call s:test_xgrep('l')
1628endfunc
1629
1630func Test_two_windows()
1631  " Use one 'errorformat' for two windows.  Add an expression to each of them,
1632  " make sure they each keep their own state.
1633  set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f'
1634  call mkdir('Xone/a', 'p')
1635  call mkdir('Xtwo/a', 'p')
1636  let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7']
1637  call writefile(lines, 'Xone/a/one.txt')
1638  call writefile(lines, 'Xtwo/a/two.txt')
1639
1640  new one
1641  let one_id = win_getid()
1642  lexpr ""
1643  new two
1644  let two_id = win_getid()
1645  lexpr ""
1646
1647  laddexpr "Entering dir 'Xtwo/a'"
1648  call win_gotoid(one_id)
1649  laddexpr "Entering dir 'Xone/a'"
1650  call win_gotoid(two_id)
1651  laddexpr 'two.txt:5:two two two'
1652  call win_gotoid(one_id)
1653  laddexpr 'one.txt:3:one one one'
1654
1655  let loc_one = getloclist(one_id)
1656  call assert_equal('Xone/a/one.txt', bufname(loc_one[1].bufnr))
1657  call assert_equal(3, loc_one[1].lnum)
1658
1659  let loc_two = getloclist(two_id)
1660  call assert_equal('Xtwo/a/two.txt', bufname(loc_two[1].bufnr))
1661  call assert_equal(5, loc_two[1].lnum)
1662
1663  call win_gotoid(one_id)
1664  bwipe!
1665  call win_gotoid(two_id)
1666  bwipe!
1667  call delete('Xone', 'rf')
1668  call delete('Xtwo', 'rf')
1669endfunc
1670
1671func XbottomTests(cchar)
1672  call s:setup_commands(a:cchar)
1673
1674  " Calling lbottom without any errors should fail
1675  if a:cchar == 'l'
1676      call assert_fails('lbottom', 'E776:')
1677  endif
1678
1679  call g:Xsetlist([{'filename': 'foo', 'lnum': 42}])
1680  Xopen
1681  let wid = win_getid()
1682  call assert_equal(1, line('.'))
1683  wincmd w
1684  call g:Xsetlist([{'filename': 'var', 'lnum': 24}], 'a')
1685  Xbottom
1686  call win_gotoid(wid)
1687  call assert_equal(2, line('.'))
1688  Xclose
1689endfunc
1690
1691" Tests for the :cbottom and :lbottom commands
1692func Test_cbottom()
1693  call XbottomTests('c')
1694  call XbottomTests('l')
1695endfunc
1696
1697func HistoryTest(cchar)
1698  call s:setup_commands(a:cchar)
1699
1700  " clear all lists after the first one, then replace the first one.
1701  call g:Xsetlist([])
1702  call assert_fails('Xolder 99', 'E380:')
1703  let entry = {'filename': 'foo', 'lnum': 42}
1704  call g:Xsetlist([entry], 'r')
1705  call g:Xsetlist([entry, entry])
1706  call g:Xsetlist([entry, entry, entry])
1707  let res = split(execute(a:cchar . 'hist'), "\n")
1708  call assert_equal(3, len(res))
1709  let common = 'errors     :set' . (a:cchar == 'c' ? 'qf' : 'loc') . 'list()'
1710  call assert_equal('  error list 1 of 3; 1 ' . common, res[0])
1711  call assert_equal('  error list 2 of 3; 2 ' . common, res[1])
1712  call assert_equal('> error list 3 of 3; 3 ' . common, res[2])
1713
1714  call g:Xsetlist([], 'f')
1715  let l = split(execute(a:cchar . 'hist'), "\n")
1716  call assert_equal('No entries', l[0])
1717endfunc
1718
1719func Test_history()
1720  call HistoryTest('c')
1721  call HistoryTest('l')
1722endfunc
1723
1724func Test_duplicate_buf()
1725  " make sure we can get the highest buffer number
1726  edit DoesNotExist
1727  edit DoesNotExist2
1728  let last_buffer = bufnr("$")
1729
1730  " make sure only one buffer is created
1731  call writefile(['this one', 'that one'], 'Xgrepthis')
1732  vimgrep one Xgrepthis
1733  vimgrep one Xgrepthis
1734  call assert_equal(last_buffer + 1, bufnr("$"))
1735
1736  call delete('Xgrepthis')
1737endfunc
1738
1739" Quickfix/Location list set/get properties tests
1740func Xproperty_tests(cchar)
1741    call s:setup_commands(a:cchar)
1742
1743    " Error cases
1744    call assert_fails('call g:Xgetlist(99)', 'E715:')
1745    call assert_fails('call g:Xsetlist(99)', 'E714:')
1746    call assert_fails('call g:Xsetlist([], "a", [])', 'E715:')
1747
1748    " Set and get the title
1749    call g:Xsetlist([])
1750    Xopen
1751    wincmd p
1752    call g:Xsetlist([{'filename':'foo', 'lnum':27}])
1753    let s = g:Xsetlist([], 'a', {'title' : 'Sample'})
1754    call assert_equal(0, s)
1755    let d = g:Xgetlist({"title":1})
1756    call assert_equal('Sample', d.title)
1757
1758    Xopen
1759    call assert_equal('Sample', w:quickfix_title)
1760    Xclose
1761
1762    " Tests for action argument
1763    silent! Xolder 999
1764    let qfnr = g:Xgetlist({'all':1}).nr
1765    call g:Xsetlist([], 'r', {'title' : 'N1'})
1766    call assert_equal('N1', g:Xgetlist({'all':1}).title)
1767    call g:Xsetlist([], ' ', {'title' : 'N2'})
1768    call assert_equal(qfnr + 1, g:Xgetlist({'all':1}).nr)
1769
1770    let res = g:Xgetlist({'nr': 0})
1771    call assert_equal(qfnr + 1, res.nr)
1772    call assert_equal(['nr'], keys(res))
1773
1774    call g:Xsetlist([], ' ', {'title' : 'N3'})
1775    call assert_equal('N2', g:Xgetlist({'nr':2, 'title':1}).title)
1776
1777    " Changing the title of an earlier quickfix list
1778    call g:Xsetlist([], 'r', {'title' : 'NewTitle', 'nr' : 2})
1779    call assert_equal('NewTitle', g:Xgetlist({'nr':2, 'title':1}).title)
1780
1781    " Changing the title of an invalid quickfix list
1782    call assert_equal(-1, g:Xsetlist([], ' ',
1783		\ {'title' : 'SomeTitle', 'nr' : 99}))
1784    call assert_equal(-1, g:Xsetlist([], ' ',
1785		\ {'title' : 'SomeTitle', 'nr' : 'abc'}))
1786
1787    if a:cchar == 'c'
1788	copen
1789	call assert_equal({'winid':win_getid()}, getqflist({'winid':1}))
1790	cclose
1791    endif
1792
1793    " Invalid arguments
1794    call assert_fails('call g:Xgetlist([])', 'E715')
1795    call assert_fails('call g:Xsetlist([], "a", [])', 'E715')
1796    let s = g:Xsetlist([], 'a', {'abc':1})
1797    call assert_equal(-1, s)
1798
1799    call assert_equal({}, g:Xgetlist({'abc':1}))
1800    call assert_equal({}, g:Xgetlist({'nr':99, 'title':1}))
1801    call assert_equal({}, g:Xgetlist({'nr':[], 'title':1}))
1802
1803    if a:cchar == 'l'
1804	call assert_equal({}, getloclist(99, {'title': 1}))
1805    endif
1806
1807    " Context related tests
1808    let s = g:Xsetlist([], 'a', {'context':[1,2,3]})
1809    call assert_equal(0, s)
1810    call test_garbagecollect_now()
1811    let d = g:Xgetlist({'context':1})
1812    call assert_equal([1,2,3], d.context)
1813    call g:Xsetlist([], 'a', {'context':{'color':'green'}})
1814    let d = g:Xgetlist({'context':1})
1815    call assert_equal({'color':'green'}, d.context)
1816    call g:Xsetlist([], 'a', {'context':"Context info"})
1817    let d = g:Xgetlist({'context':1})
1818    call assert_equal("Context info", d.context)
1819    call g:Xsetlist([], 'a', {'context':246})
1820    let d = g:Xgetlist({'context':1})
1821    call assert_equal(246, d.context)
1822    if a:cchar == 'l'
1823	" Test for copying context across two different location lists
1824	new | only
1825	let w1_id = win_getid()
1826	let l = [1]
1827	call setloclist(0, [], 'a', {'context':l})
1828	new
1829	let w2_id = win_getid()
1830	call add(l, 2)
1831	call assert_equal([1, 2], getloclist(w1_id, {'context':1}).context)
1832	call assert_equal([1, 2], getloclist(w2_id, {'context':1}).context)
1833	unlet! l
1834	call assert_equal([1, 2], getloclist(w2_id, {'context':1}).context)
1835	only
1836	call setloclist(0, [], 'f')
1837	call assert_equal({}, getloclist(0, {'context':1}))
1838    endif
1839
1840    " Test for changing the context of previous quickfix lists
1841    call g:Xsetlist([], 'f')
1842    Xexpr "One"
1843    Xexpr "Two"
1844    Xexpr "Three"
1845    call g:Xsetlist([], 'r', {'context' : [1], 'nr' : 1})
1846    call g:Xsetlist([], 'a', {'context' : [2], 'nr' : 2})
1847    " Also, check for setting the context using quickfix list number zero.
1848    call g:Xsetlist([], 'r', {'context' : [3], 'nr' : 0})
1849    call test_garbagecollect_now()
1850    let l = g:Xgetlist({'nr' : 1, 'context' : 1})
1851    call assert_equal([1], l.context)
1852    let l = g:Xgetlist({'nr' : 2, 'context' : 1})
1853    call assert_equal([2], l.context)
1854    let l = g:Xgetlist({'nr' : 3, 'context' : 1})
1855    call assert_equal([3], l.context)
1856
1857    " Test for changing the context through reference and for garbage
1858    " collection of quickfix context
1859    let l = ["red"]
1860    call g:Xsetlist([], ' ', {'context' : l})
1861    call add(l, "blue")
1862    let x = g:Xgetlist({'context' : 1})
1863    call add(x.context, "green")
1864    call assert_equal(["red", "blue", "green"], l)
1865    call assert_equal(["red", "blue", "green"], x.context)
1866    unlet l
1867    call test_garbagecollect_now()
1868    let m = g:Xgetlist({'context' : 1})
1869    call assert_equal(["red", "blue", "green"], m.context)
1870
1871    " Test for setting/getting items
1872    Xexpr ""
1873    let qfprev = g:Xgetlist({'nr':0})
1874    let s = g:Xsetlist([], ' ', {'title':'Green',
1875		\ 'items' : [{'filename':'F1', 'lnum':10}]})
1876    call assert_equal(0, s)
1877    let qfcur = g:Xgetlist({'nr':0})
1878    call assert_true(qfcur.nr == qfprev.nr + 1)
1879    let l = g:Xgetlist({'items':1})
1880    call assert_equal('F1', bufname(l.items[0].bufnr))
1881    call assert_equal(10, l.items[0].lnum)
1882    call g:Xsetlist([], 'a', {'items' : [{'filename':'F2', 'lnum':20},
1883		\  {'filename':'F2', 'lnum':30}]})
1884    let l = g:Xgetlist({'items':1})
1885    call assert_equal('F2', bufname(l.items[2].bufnr))
1886    call assert_equal(30, l.items[2].lnum)
1887    call g:Xsetlist([], 'r', {'items' : [{'filename':'F3', 'lnum':40}]})
1888    let l = g:Xgetlist({'items':1})
1889    call assert_equal('F3', bufname(l.items[0].bufnr))
1890    call assert_equal(40, l.items[0].lnum)
1891    call g:Xsetlist([], 'r', {'items' : []})
1892    let l = g:Xgetlist({'items':1})
1893    call assert_equal(0, len(l.items))
1894
1895    call g:Xsetlist([], 'r', {'title' : 'TestTitle'})
1896    call g:Xsetlist([], 'r', {'items' : [{'filename' : 'F1', 'lnum' : 10, 'text' : 'L10'}]})
1897    call g:Xsetlist([], 'r', {'items' : [{'filename' : 'F1', 'lnum' : 10, 'text' : 'L10'}]})
1898    call assert_equal('TestTitle', g:Xgetlist({'title' : 1}).title)
1899
1900    " The following used to crash Vim with address sanitizer
1901    call g:Xsetlist([], 'f')
1902    call g:Xsetlist([], 'a', {'items' : [{'filename':'F1', 'lnum':10}]})
1903    call assert_equal(10, g:Xgetlist({'items':1}).items[0].lnum)
1904
1905    " Save and restore the quickfix stack
1906    call g:Xsetlist([], 'f')
1907    call assert_equal(0, g:Xgetlist({'nr':'$'}).nr)
1908    Xexpr "File1:10:Line1"
1909    Xexpr "File2:20:Line2"
1910    Xexpr "File3:30:Line3"
1911    let last_qf = g:Xgetlist({'nr':'$'}).nr
1912    call assert_equal(3, last_qf)
1913    let qstack = []
1914    for i in range(1, last_qf)
1915	let qstack = add(qstack, g:Xgetlist({'nr':i, 'all':1}))
1916    endfor
1917    call g:Xsetlist([], 'f')
1918    for i in range(len(qstack))
1919	call g:Xsetlist([], ' ', qstack[i])
1920    endfor
1921    call assert_equal(3, g:Xgetlist({'nr':'$'}).nr)
1922    call assert_equal(10, g:Xgetlist({'nr':1, 'items':1}).items[0].lnum)
1923    call assert_equal(20, g:Xgetlist({'nr':2, 'items':1}).items[0].lnum)
1924    call assert_equal(30, g:Xgetlist({'nr':3, 'items':1}).items[0].lnum)
1925    call g:Xsetlist([], 'f')
1926
1927    " Swap two quickfix lists
1928    Xexpr "File1:10:Line10"
1929    Xexpr "File2:20:Line20"
1930    Xexpr "File3:30:Line30"
1931    call g:Xsetlist([], 'r', {'nr':1,'title':'Colors','context':['Colors']})
1932    call g:Xsetlist([], 'r', {'nr':2,'title':'Fruits','context':['Fruits']})
1933    let l1=g:Xgetlist({'nr':1,'all':1})
1934    let l2=g:Xgetlist({'nr':2,'all':1})
1935    let save_id = l1.id
1936    let l1.id=l2.id
1937    let l2.id=save_id
1938    call g:Xsetlist([], 'r', l1)
1939    call g:Xsetlist([], 'r', l2)
1940    let newl1=g:Xgetlist({'nr':1,'all':1})
1941    let newl2=g:Xgetlist({'nr':2,'all':1})
1942    call assert_equal('Fruits', newl1.title)
1943    call assert_equal(['Fruits'], newl1.context)
1944    call assert_equal('Line20', newl1.items[0].text)
1945    call assert_equal('Colors', newl2.title)
1946    call assert_equal(['Colors'], newl2.context)
1947    call assert_equal('Line10', newl2.items[0].text)
1948    call g:Xsetlist([], 'f')
1949endfunc
1950
1951func Test_qf_property()
1952    call Xproperty_tests('c')
1953    call Xproperty_tests('l')
1954endfunc
1955
1956" Tests for the QuickFixCmdPre/QuickFixCmdPost autocommands
1957func QfAutoCmdHandler(loc, cmd)
1958  call add(g:acmds, a:loc . a:cmd)
1959endfunc
1960
1961func Test_Autocmd()
1962  autocmd QuickFixCmdPre * call QfAutoCmdHandler('pre', expand('<amatch>'))
1963  autocmd QuickFixCmdPost * call QfAutoCmdHandler('post', expand('<amatch>'))
1964
1965  let g:acmds = []
1966  cexpr "F1:10:Line 10"
1967  caddexpr "F1:20:Line 20"
1968  cgetexpr "F1:30:Line 30"
1969  enew! | call append(0, "F2:10:Line 10")
1970  cbuffer!
1971  enew! | call append(0, "F2:20:Line 20")
1972  cgetbuffer
1973  enew! | call append(0, "F2:30:Line 30")
1974  caddbuffer
1975
1976  let l = ['precexpr',
1977	      \ 'postcexpr',
1978	      \ 'precaddexpr',
1979	      \ 'postcaddexpr',
1980	      \ 'precgetexpr',
1981	      \ 'postcgetexpr',
1982	      \ 'precbuffer',
1983	      \ 'postcbuffer',
1984	      \ 'precgetbuffer',
1985	      \ 'postcgetbuffer',
1986	      \ 'precaddbuffer',
1987	      \ 'postcaddbuffer']
1988  call assert_equal(l, g:acmds)
1989endfunc
1990
1991func Test_Autocmd_Exception()
1992  set efm=%m
1993  lgetexpr '?'
1994
1995  try
1996    call DoesNotExit()
1997  catch
1998    lgetexpr '1'
1999  finally
2000    lgetexpr '1'
2001  endtry
2002
2003  call assert_equal('1', getloclist(0)[0].text)
2004
2005  set efm&vim
2006endfunc
2007
2008func Test_caddbuffer_wrong()
2009  " This used to cause a memory access in freed memory.
2010  let save_efm = &efm
2011  set efm=%EEEE%m,%WWWW,%+CCCC%>%#,%GGGG%.#
2012  cgetexpr ['WWWW', 'EEEE', 'CCCC']
2013  let &efm = save_efm
2014  caddbuffer
2015  bwipe!
2016endfunc
2017
2018func Test_caddexpr_wrong()
2019  " This used to cause a memory access in freed memory.
2020  cbuffer
2021  cbuffer
2022  copen
2023  let save_efm = &efm
2024  set efm=%
2025  call assert_fails('caddexpr ""', 'E376:')
2026  let &efm = save_efm
2027endfunc
2028
2029func Test_dirstack_cleanup()
2030  " This used to cause a memory access in freed memory.
2031  let save_efm = &efm
2032  lexpr '0'
2033  lopen
2034  fun X(c)
2035    let save_efm=&efm
2036    set efm=%D%f
2037    if a:c == 'c'
2038      caddexpr '::'
2039    else
2040      laddexpr ':0:0'
2041    endif
2042    let &efm=save_efm
2043  endfun
2044  call X('c')
2045  call X('l')
2046  call setqflist([], 'r')
2047  caddbuffer
2048  let &efm = save_efm
2049endfunc
2050
2051" Tests for jumping to entries from the location list window and quickfix
2052" window
2053func Test_cwindow_jump()
2054  set efm=%f%%%l%%%m
2055  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2056  lopen | only
2057  lfirst
2058  call assert_true(winnr('$') == 2)
2059  call assert_true(winnr() == 1)
2060  " Location list for the new window should be set
2061  call assert_true(getloclist(0)[2].text == 'Line 30')
2062
2063  " Open a scratch buffer
2064  " Open a new window and create a location list
2065  " Open the location list window and close the other window
2066  " Jump to an entry.
2067  " Should create a new window and jump to the entry. The scrtach buffer
2068  " should not be used.
2069  enew | only
2070  set buftype=nofile
2071  below new
2072  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2073  lopen
2074  2wincmd c
2075  lnext
2076  call assert_true(winnr('$') == 3)
2077  call assert_true(winnr() == 2)
2078
2079  " Open two windows with two different location lists
2080  " Open the location list window and close the previous window
2081  " Jump to an entry in the location list window
2082  " Should open the file in the first window and not set the location list.
2083  enew | only
2084  lgetexpr ["F1%5%Line 5"]
2085  below new
2086  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2087  lopen
2088  2wincmd c
2089  lnext
2090  call assert_true(winnr() == 1)
2091  call assert_true(getloclist(0)[0].text == 'Line 5')
2092
2093  enew | only
2094  cgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2095  copen
2096  cnext
2097  call assert_true(winnr('$') == 2)
2098  call assert_true(winnr() == 1)
2099
2100  enew | only
2101  set efm&vim
2102endfunc
2103
2104func XvimgrepTests(cchar)
2105  call s:setup_commands(a:cchar)
2106
2107  call writefile(['Editor:VIM vim',
2108	      \ 'Editor:Emacs EmAcS',
2109	      \ 'Editor:Notepad NOTEPAD'], 'Xtestfile1')
2110  call writefile(['Linux', 'MacOS', 'MS-Windows'], 'Xtestfile2')
2111
2112  " Error cases
2113  call assert_fails('Xvimgrep /abc *', 'E682:')
2114
2115  let @/=''
2116  call assert_fails('Xvimgrep // *', 'E35:')
2117
2118  call assert_fails('Xvimgrep abc', 'E683:')
2119  call assert_fails('Xvimgrep a1b2c3 Xtestfile1', 'E480:')
2120  call assert_fails('Xvimgrep pat Xa1b2c3', 'E480:')
2121
2122  Xexpr ""
2123  Xvimgrepadd Notepad Xtestfile1
2124  Xvimgrepadd MacOS Xtestfile2
2125  let l = g:Xgetlist()
2126  call assert_equal(2, len(l))
2127  call assert_equal('Editor:Notepad NOTEPAD', l[0].text)
2128
2129  Xvimgrep #\cvim#g Xtestfile?
2130  let l = g:Xgetlist()
2131  call assert_equal(2, len(l))
2132  call assert_equal(8, l[0].col)
2133  call assert_equal(12, l[1].col)
2134
2135  1Xvimgrep ?Editor? Xtestfile*
2136  let l = g:Xgetlist()
2137  call assert_equal(1, len(l))
2138  call assert_equal('Editor:VIM vim', l[0].text)
2139
2140  edit +3 Xtestfile2
2141  Xvimgrep +\cemacs+j Xtestfile1
2142  let l = g:Xgetlist()
2143  call assert_equal('Xtestfile2', bufname(''))
2144  call assert_equal('Editor:Emacs EmAcS', l[0].text)
2145
2146  call delete('Xtestfile1')
2147  call delete('Xtestfile2')
2148endfunc
2149
2150" Tests for the :vimgrep command
2151func Test_vimgrep()
2152  call XvimgrepTests('c')
2153  call XvimgrepTests('l')
2154endfunc
2155
2156func XfreeTests(cchar)
2157  call s:setup_commands(a:cchar)
2158
2159  enew | only
2160
2161  " Deleting the quickfix stack should work even When the current list is
2162  " somewhere in the middle of the stack
2163  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2164  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2165  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2166  Xolder
2167  call g:Xsetlist([], 'f')
2168  call assert_equal(0, len(g:Xgetlist()))
2169
2170  " After deleting the stack, adding a new list should create a stack with a
2171  " single list.
2172  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2173  call assert_equal(1, g:Xgetlist({'all':1}).nr)
2174
2175  " Deleting the stack from a quickfix window should update/clear the
2176  " quickfix/location list window.
2177  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2178  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2179  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2180  Xolder
2181  Xwindow
2182  call g:Xsetlist([], 'f')
2183  call assert_equal(2, winnr('$'))
2184  call assert_equal(1, line('$'))
2185  Xclose
2186
2187  " Deleting the stack from a non-quickfix window should update/clear the
2188  " quickfix/location list window.
2189  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2190  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2191  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2192  Xolder
2193  Xwindow
2194  wincmd p
2195  call g:Xsetlist([], 'f')
2196  call assert_equal(0, len(g:Xgetlist()))
2197  wincmd p
2198  call assert_equal(2, winnr('$'))
2199  call assert_equal(1, line('$'))
2200
2201  " After deleting the location list stack, if the location list window is
2202  " opened, then a new location list should be created. So opening the
2203  " location list window again should not create a new window.
2204  if a:cchar == 'l'
2205      lexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2206      wincmd p
2207      lopen
2208      call assert_equal(2, winnr('$'))
2209  endif
2210  Xclose
2211endfunc
2212
2213" Tests for the quickifx free functionality
2214func Test_qf_free()
2215  call XfreeTests('c')
2216  call XfreeTests('l')
2217endfunc
2218
2219" Test for buffer overflow when parsing lines and adding new entries to
2220" the quickfix list.
2221func Test_bufoverflow()
2222  set efm=%f:%l:%m
2223  cgetexpr ['File1:100:' . repeat('x', 1025)]
2224
2225  set efm=%+GCompiler:\ %.%#,%f:%l:%m
2226  cgetexpr ['Compiler: ' . repeat('a', 1015), 'File1:10:Hello World']
2227
2228  set efm=%DEntering\ directory\ %f,%f:%l:%m
2229  cgetexpr ['Entering directory ' . repeat('a', 1006),
2230	      \ 'File1:10:Hello World']
2231  set efm&vim
2232endfunc
2233
2234" Tests for getting the quickfix stack size
2235func XsizeTests(cchar)
2236  call s:setup_commands(a:cchar)
2237
2238  call g:Xsetlist([], 'f')
2239  call assert_equal(0, g:Xgetlist({'nr':'$'}).nr)
2240  call assert_equal(1, len(g:Xgetlist({'nr':'$', 'all':1})))
2241  call assert_equal(0, len(g:Xgetlist({'nr':0})))
2242
2243  Xexpr "File1:10:Line1"
2244  Xexpr "File2:20:Line2"
2245  Xexpr "File3:30:Line3"
2246  Xolder | Xolder
2247  call assert_equal(3, g:Xgetlist({'nr':'$'}).nr)
2248  call g:Xsetlist([], 'f')
2249
2250  Xexpr "File1:10:Line1"
2251  Xexpr "File2:20:Line2"
2252  Xexpr "File3:30:Line3"
2253  Xolder | Xolder
2254  call g:Xsetlist([], 'a', {'nr':'$', 'title':'Compiler'})
2255  call assert_equal('Compiler', g:Xgetlist({'nr':3, 'all':1}).title)
2256endfunc
2257
2258func Test_Qf_Size()
2259  call XsizeTests('c')
2260  call XsizeTests('l')
2261endfunc
2262
2263func Test_cclose_from_copen()
2264    augroup QF_Test
2265	au!
2266        au FileType qf :call assert_fails(':cclose', 'E788')
2267    augroup END
2268    copen
2269    augroup QF_Test
2270	au!
2271    augroup END
2272    augroup! QF_Test
2273endfunc
2274
2275func Test_cclose_in_autocmd()
2276  " Problem is only triggered if "starting" is zero, so that the OptionsSet
2277  " event will be triggered.
2278  call test_override('starting', 1)
2279  augroup QF_Test
2280    au!
2281    au FileType qf :call assert_fails(':cclose', 'E788')
2282  augroup END
2283  copen
2284  augroup QF_Test
2285    au!
2286  augroup END
2287  augroup! QF_Test
2288  call test_override('starting', 0)
2289endfunc
2290
2291func Test_resize_from_copen()
2292    augroup QF_Test
2293	au!
2294        au FileType qf resize 5
2295    augroup END
2296    try
2297	" This should succeed without any exception.  No other buffers are
2298	" involved in the autocmd.
2299	copen
2300    finally
2301	augroup QF_Test
2302	    au!
2303	augroup END
2304	augroup! QF_Test
2305    endtry
2306endfunc
2307
2308" Tests for the quickfix buffer b:changedtick variable
2309func Xchangedtick_tests(cchar)
2310  call s:setup_commands(a:cchar)
2311
2312  new | only
2313
2314  Xexpr "" | Xexpr "" | Xexpr ""
2315
2316  Xopen
2317  Xolder
2318  Xolder
2319  Xaddexpr "F1:10:Line10"
2320  Xaddexpr "F2:20:Line20"
2321  call g:Xsetlist([{"filename":"F3", "lnum":30, "text":"Line30"}], 'a')
2322  call g:Xsetlist([], 'f')
2323  call assert_equal(8, getbufvar('%', 'changedtick'))
2324  Xclose
2325endfunc
2326
2327func Test_changedtick()
2328  call Xchangedtick_tests('c')
2329  call Xchangedtick_tests('l')
2330endfunc
2331
2332" Tests for parsing an expression using setqflist()
2333func Xsetexpr_tests(cchar)
2334  call s:setup_commands(a:cchar)
2335
2336  let t = ["File1:10:Line10", "File1:20:Line20"]
2337  call g:Xsetlist([], ' ', {'lines' : t})
2338  call g:Xsetlist([], 'a', {'lines' : ["File1:30:Line30"]})
2339
2340  let l = g:Xgetlist()
2341  call assert_equal(3, len(l))
2342  call assert_equal(20, l[1].lnum)
2343  call assert_equal('Line30', l[2].text)
2344  call g:Xsetlist([], 'r', {'lines' : ["File2:5:Line5"]})
2345  let l = g:Xgetlist()
2346  call assert_equal(1, len(l))
2347  call assert_equal('Line5', l[0].text)
2348  call assert_equal(-1, g:Xsetlist([], 'a', {'lines' : 10}))
2349  call assert_equal(-1, g:Xsetlist([], 'a', {'lines' : "F1:10:L10"}))
2350
2351  call g:Xsetlist([], 'f')
2352  " Add entries to multiple lists
2353  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["File1:10:Line10"]})
2354  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["File2:20:Line20"]})
2355  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["File1:15:Line15"]})
2356  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["File2:25:Line25"]})
2357  call assert_equal('Line15', g:Xgetlist({'nr':1, 'items':1}).items[1].text)
2358  call assert_equal('Line25', g:Xgetlist({'nr':2, 'items':1}).items[1].text)
2359
2360  " Adding entries using a custom efm
2361  set efm&
2362  call g:Xsetlist([], ' ', {'efm' : '%f#%l#%m',
2363				\ 'lines' : ["F1#10#L10", "F2#20#L20"]})
2364  call assert_equal(20, g:Xgetlist({'items':1}).items[1].lnum)
2365  call g:Xsetlist([], 'a', {'efm' : '%f#%l#%m', 'lines' : ["F3:30:L30"]})
2366  call assert_equal('F3:30:L30', g:Xgetlist({'items':1}).items[2].text)
2367  call assert_equal(20, g:Xgetlist({'items':1}).items[1].lnum)
2368  call assert_equal(-1, g:Xsetlist([], 'a', {'efm' : [],
2369				\ 'lines' : ['F1:10:L10']}))
2370endfunc
2371
2372func Test_setexpr()
2373  call Xsetexpr_tests('c')
2374  call Xsetexpr_tests('l')
2375endfunc
2376
2377" Tests for per quickfix/location list directory stack
2378func Xmultidirstack_tests(cchar)
2379  call s:setup_commands(a:cchar)
2380
2381  call g:Xsetlist([], 'f')
2382  Xexpr "" | Xexpr ""
2383
2384  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["Entering dir 'Xone/a'"]})
2385  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["Entering dir 'Xtwo/a'"]})
2386  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["one.txt:3:one one one"]})
2387  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["two.txt:5:two two two"]})
2388
2389  let l1 = g:Xgetlist({'nr':1, 'items':1})
2390  let l2 = g:Xgetlist({'nr':2, 'items':1})
2391  call assert_equal('Xone/a/one.txt', bufname(l1.items[1].bufnr))
2392  call assert_equal(3, l1.items[1].lnum)
2393  call assert_equal('Xtwo/a/two.txt', bufname(l2.items[1].bufnr))
2394  call assert_equal(5, l2.items[1].lnum)
2395endfunc
2396
2397func Test_multidirstack()
2398  call mkdir('Xone/a', 'p')
2399  call mkdir('Xtwo/a', 'p')
2400  let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7']
2401  call writefile(lines, 'Xone/a/one.txt')
2402  call writefile(lines, 'Xtwo/a/two.txt')
2403  let save_efm = &efm
2404  set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f'
2405
2406  call Xmultidirstack_tests('c')
2407  call Xmultidirstack_tests('l')
2408
2409  let &efm = save_efm
2410  call delete('Xone', 'rf')
2411  call delete('Xtwo', 'rf')
2412endfunc
2413
2414" Tests for per quickfix/location list file stack
2415func Xmultifilestack_tests(cchar)
2416  call s:setup_commands(a:cchar)
2417
2418  call g:Xsetlist([], 'f')
2419  Xexpr "" | Xexpr ""
2420
2421  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["[one.txt]"]})
2422  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["[two.txt]"]})
2423  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["(3,5) one one one"]})
2424  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["(5,9) two two two"]})
2425
2426  let l1 = g:Xgetlist({'nr':1, 'items':1})
2427  let l2 = g:Xgetlist({'nr':2, 'items':1})
2428  call assert_equal('one.txt', bufname(l1.items[1].bufnr))
2429  call assert_equal(3, l1.items[1].lnum)
2430  call assert_equal('two.txt', bufname(l2.items[1].bufnr))
2431  call assert_equal(5, l2.items[1].lnum)
2432endfunc
2433
2434func Test_multifilestack()
2435  let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7']
2436  call writefile(lines, 'one.txt')
2437  call writefile(lines, 'two.txt')
2438  let save_efm = &efm
2439  set efm=%+P[%f],(%l\\,%c)\ %m,%-Q
2440
2441  call Xmultifilestack_tests('c')
2442  call Xmultifilestack_tests('l')
2443
2444  let &efm = save_efm
2445  call delete('one.txt')
2446  call delete('two.txt')
2447endfunc
2448
2449" Tests for per buffer 'efm' setting
2450func Test_perbuf_efm()
2451  call writefile(["File1-10-Line10"], 'one.txt')
2452  call writefile(["File2#20#Line20"], 'two.txt')
2453  set efm=%f#%l#%m
2454  new | only
2455  new
2456  setlocal efm=%f-%l-%m
2457  cfile one.txt
2458  wincmd w
2459  caddfile two.txt
2460
2461  let l = getqflist()
2462  call assert_equal(10, l[0].lnum)
2463  call assert_equal('Line20', l[1].text)
2464
2465  set efm&
2466  new | only
2467  call delete('one.txt')
2468  call delete('two.txt')
2469endfunc
2470
2471" Open multiple help windows using ":lhelpgrep
2472" This test used to crash Vim
2473func Test_Multi_LL_Help()
2474    new | only
2475    lhelpgrep window
2476    lopen
2477    e#
2478    lhelpgrep buffer
2479    call assert_equal(3, winnr('$'))
2480    call assert_true(len(getloclist(1)) != 0)
2481    call assert_true(len(getloclist(2)) != 0)
2482    new | only
2483endfunc
2484
2485" Tests for adding new quickfix lists using setqflist()
2486func XaddQf_tests(cchar)
2487  call s:setup_commands(a:cchar)
2488
2489  " Create a new list using ' ' for action
2490  call g:Xsetlist([], 'f')
2491  call g:Xsetlist([], ' ', {'title' : 'Test1'})
2492  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2493  call assert_equal(1, l.nr)
2494  call assert_equal('Test1', l.title)
2495
2496  " Create a new list using ' ' for action and '$' for 'nr'
2497  call g:Xsetlist([], 'f')
2498  call g:Xsetlist([], ' ', {'title' : 'Test2', 'nr' : '$'})
2499  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2500  call assert_equal(1, l.nr)
2501  call assert_equal('Test2', l.title)
2502
2503  " Create a new list using 'a' for action
2504  call g:Xsetlist([], 'f')
2505  call g:Xsetlist([], 'a', {'title' : 'Test3'})
2506  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2507  call assert_equal(1, l.nr)
2508  call assert_equal('Test3', l.title)
2509
2510  " Create a new list using 'a' for action and '$' for 'nr'
2511  call g:Xsetlist([], 'f')
2512  call g:Xsetlist([], 'a', {'title' : 'Test3', 'nr' : '$'})
2513  call g:Xsetlist([], 'a', {'title' : 'Test4'})
2514  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2515  call assert_equal(1, l.nr)
2516  call assert_equal('Test4', l.title)
2517
2518  " Adding a quickfix list should remove all the lists following the current
2519  " list.
2520  Xexpr "" | Xexpr "" | Xexpr ""
2521  silent! 10Xolder
2522  call g:Xsetlist([], ' ', {'title' : 'Test5'})
2523  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2524  call assert_equal(2, l.nr)
2525  call assert_equal('Test5', l.title)
2526
2527  " Add a quickfix list using '$' as the list number.
2528  let lastqf = g:Xgetlist({'nr':'$'}).nr
2529  silent! 99Xolder
2530  call g:Xsetlist([], ' ', {'nr' : '$', 'title' : 'Test6'})
2531  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2532  call assert_equal(lastqf + 1, l.nr)
2533  call assert_equal('Test6', l.title)
2534
2535  " Add a quickfix list using 'nr' set to one more than the quickfix
2536  " list size.
2537  let lastqf = g:Xgetlist({'nr':'$'}).nr
2538  silent! 99Xolder
2539  call g:Xsetlist([], ' ', {'nr' : lastqf + 1, 'title' : 'Test7'})
2540  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2541  call assert_equal(lastqf + 1, l.nr)
2542  call assert_equal('Test7', l.title)
2543
2544  " Add a quickfix list to a stack with 10 lists using 'nr' set to '$'
2545  exe repeat('Xexpr "" |', 9) . 'Xexpr ""'
2546  silent! 99Xolder
2547  call g:Xsetlist([], ' ', {'nr' : '$', 'title' : 'Test8'})
2548  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2549  call assert_equal(10, l.nr)
2550  call assert_equal('Test8', l.title)
2551
2552  " Add a quickfix list using 'nr' set to a value greater than 10
2553  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : 12, 'title' : 'Test9'}))
2554
2555  " Try adding a quickfix list with 'nr' set to a value greater than the
2556  " quickfix list size but less than 10.
2557  call g:Xsetlist([], 'f')
2558  Xexpr "" | Xexpr "" | Xexpr ""
2559  silent! 99Xolder
2560  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : 8, 'title' : 'Test10'}))
2561
2562  " Add a quickfix list using 'nr' set to a some string or list
2563  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : [1,2], 'title' : 'Test11'}))
2564endfunc
2565
2566func Test_add_qf()
2567  call XaddQf_tests('c')
2568  call XaddQf_tests('l')
2569endfunc
2570
2571" Test for getting the quickfix list items from some text without modifying
2572" the quickfix stack
2573func XgetListFromLines(cchar)
2574  call s:setup_commands(a:cchar)
2575  call g:Xsetlist([], 'f')
2576
2577  let l = g:Xgetlist({'lines' : ["File2:20:Line20", "File2:30:Line30"]}).items
2578  call assert_equal(2, len(l))
2579  call assert_equal(30, l[1].lnum)
2580
2581  call assert_equal({}, g:Xgetlist({'lines' : 10}))
2582  call assert_equal({}, g:Xgetlist({'lines' : 'File1:10:Line10'}))
2583  call assert_equal([], g:Xgetlist({'lines' : []}).items)
2584  call assert_equal([], g:Xgetlist({'lines' : [10, 20]}).items)
2585
2586  " Parse text using a custom efm
2587  set efm&
2588  let l = g:Xgetlist({'lines':['File3#30#Line30'], 'efm' : '%f#%l#%m'}).items
2589  call assert_equal('Line30', l[0].text)
2590  let l = g:Xgetlist({'lines':['File3:30:Line30'], 'efm' : '%f-%l-%m'}).items
2591  call assert_equal('File3:30:Line30', l[0].text)
2592  let l = g:Xgetlist({'lines':['File3:30:Line30'], 'efm' : [1,2]})
2593  call assert_equal({}, l)
2594  call assert_fails("call g:Xgetlist({'lines':['abc'], 'efm':'%2'})", 'E376:')
2595  call assert_fails("call g:Xgetlist({'lines':['abc'], 'efm':''})", 'E378:')
2596
2597  " Make sure that the quickfix stack is not modified
2598  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
2599endfunc
2600
2601func Test_get_list_from_lines()
2602  call XgetListFromLines('c')
2603  call XgetListFromLines('l')
2604endfunc
2605
2606" Tests for the quickfix list id
2607func Xqfid_tests(cchar)
2608  call s:setup_commands(a:cchar)
2609
2610  call g:Xsetlist([], 'f')
2611  call assert_equal({}, g:Xgetlist({'id':0}))
2612  Xexpr ''
2613  let start_id = g:Xgetlist({'id' : 0}).id
2614  Xexpr '' | Xexpr ''
2615  Xolder
2616  call assert_equal(start_id, g:Xgetlist({'id':0, 'nr':1}).id)
2617  call assert_equal(start_id + 1, g:Xgetlist({'id':0, 'nr':0}).id)
2618  call assert_equal(start_id + 2, g:Xgetlist({'id':0, 'nr':'$'}).id)
2619  call assert_equal({}, g:Xgetlist({'id':0, 'nr':99}))
2620  call assert_equal(2, g:Xgetlist({'id':start_id + 1, 'nr':0}).nr)
2621  call assert_equal({}, g:Xgetlist({'id':99, 'nr':0}))
2622  call assert_equal({}, g:Xgetlist({'id':"abc", 'nr':0}))
2623
2624  call g:Xsetlist([], 'a', {'id':start_id, 'context':[1,2]})
2625  call assert_equal([1,2], g:Xgetlist({'nr':1, 'context':1}).context)
2626  call g:Xsetlist([], 'a', {'id':start_id+1, 'lines':['F1:10:L10']})
2627  call assert_equal('L10', g:Xgetlist({'nr':2, 'items':1}).items[0].text)
2628  call assert_equal(-1, g:Xsetlist([], 'a', {'id':999, 'title':'Vim'}))
2629  call assert_equal(-1, g:Xsetlist([], 'a', {'id':'abc', 'title':'Vim'}))
2630
2631  let qfid = g:Xgetlist({'id':0, 'nr':0})
2632  call g:Xsetlist([], 'f')
2633  call assert_equal({}, g:Xgetlist({'id':qfid, 'nr':0}))
2634endfunc
2635
2636func Test_qf_id()
2637  call Xqfid_tests('c')
2638  call Xqfid_tests('l')
2639endfunc
2640