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  cexpr ""
1970  caddexpr ""
1971  cgetexpr ""
1972  silent! cexpr non_existing_func()
1973  silent! caddexpr non_existing_func()
1974  silent! cgetexpr non_existing_func()
1975  let l = ['precexpr',
1976	      \ 'postcexpr',
1977	      \ 'precaddexpr',
1978	      \ 'postcaddexpr',
1979	      \ 'precgetexpr',
1980	      \ 'postcgetexpr',
1981	      \ 'precexpr',
1982	      \ 'postcexpr',
1983	      \ 'precaddexpr',
1984	      \ 'postcaddexpr',
1985	      \ 'precgetexpr',
1986	      \ 'postcgetexpr',
1987	      \ 'precexpr',
1988	      \ 'precaddexpr',
1989	      \ 'precgetexpr']
1990  call assert_equal(l, g:acmds)
1991
1992  let g:acmds = []
1993  enew! | call append(0, "F2:10:Line 10")
1994  cbuffer!
1995  enew! | call append(0, "F2:20:Line 20")
1996  cgetbuffer
1997  enew! | call append(0, "F2:30:Line 30")
1998  caddbuffer
1999  new
2000  let bnum = bufnr('%')
2001  bunload
2002  exe 'silent! cbuffer! ' . bnum
2003  exe 'silent! cgetbuffer ' . bnum
2004  exe 'silent! caddbuffer ' . bnum
2005  enew!
2006  let l = ['precbuffer',
2007	      \ 'postcbuffer',
2008	      \ 'precgetbuffer',
2009	      \ 'postcgetbuffer',
2010	      \ 'precaddbuffer',
2011	      \ 'postcaddbuffer',
2012	      \ 'precbuffer',
2013	      \ 'precgetbuffer',
2014	      \ 'precaddbuffer']
2015  call assert_equal(l, g:acmds)
2016
2017  call writefile(['Xtest:1:Line1'], 'Xtest')
2018  call writefile([], 'Xempty')
2019  let g:acmds = []
2020  cfile Xtest
2021  caddfile Xtest
2022  cgetfile Xtest
2023  cfile Xempty
2024  caddfile Xempty
2025  cgetfile Xempty
2026  silent! cfile do_not_exist
2027  silent! caddfile do_not_exist
2028  silent! cgetfile do_not_exist
2029  let l = ['precfile',
2030	      \ 'postcfile',
2031	      \ 'precaddfile',
2032	      \ 'postcaddfile',
2033	      \ 'precgetfile',
2034	      \ 'postcgetfile',
2035	      \ 'precfile',
2036	      \ 'postcfile',
2037	      \ 'precaddfile',
2038	      \ 'postcaddfile',
2039	      \ 'precgetfile',
2040	      \ 'postcgetfile',
2041	      \ 'precfile',
2042	      \ 'postcfile',
2043	      \ 'precaddfile',
2044	      \ 'postcaddfile',
2045	      \ 'precgetfile',
2046	      \ 'postcgetfile']
2047  call assert_equal(l, g:acmds)
2048
2049  let g:acmds = []
2050  helpgrep quickfix
2051  silent! helpgrep non_existing_help_topic
2052  vimgrep test Xtest
2053  vimgrepadd test Xtest
2054  silent! vimgrep non_existing_test Xtest
2055  silent! vimgrepadd non_existing_test Xtest
2056  set makeprg=
2057  silent! make
2058  set makeprg&
2059  let l = ['prehelpgrep',
2060	      \ 'posthelpgrep',
2061	      \ 'prehelpgrep',
2062	      \ 'posthelpgrep',
2063	      \ 'previmgrep',
2064	      \ 'postvimgrep',
2065	      \ 'previmgrepadd',
2066	      \ 'postvimgrepadd',
2067	      \ 'previmgrep',
2068	      \ 'postvimgrep',
2069	      \ 'previmgrepadd',
2070	      \ 'postvimgrepadd',
2071	      \ 'premake',
2072	      \ 'postmake']
2073  call assert_equal(l, g:acmds)
2074
2075  if has('unix')
2076    " Run this test only on Unix-like systems. The grepprg may not be set on
2077    " non-Unix systems.
2078    " The following lines are used for the grep test. Don't remove.
2079    " Grep_Autocmd_Text: Match 1
2080    " GrepAdd_Autocmd_Text: Match 2
2081    let g:acmds = []
2082    silent grep Grep_Autocmd_Text test_quickfix.vim
2083    silent grepadd GrepAdd_Autocmd_Text test_quickfix.vim
2084    silent grep abc123def Xtest
2085    silent grepadd abc123def Xtest
2086    let l = ['pregrep',
2087		\ 'postgrep',
2088		\ 'pregrepadd',
2089		\ 'postgrepadd',
2090		\ 'pregrep',
2091		\ 'postgrep',
2092		\ 'pregrepadd',
2093		\ 'postgrepadd']
2094    call assert_equal(l, g:acmds)
2095  endif
2096
2097  call delete('Xtest')
2098  call delete('Xempty')
2099endfunc
2100
2101func Test_Autocmd_Exception()
2102  set efm=%m
2103  lgetexpr '?'
2104
2105  try
2106    call DoesNotExit()
2107  catch
2108    lgetexpr '1'
2109  finally
2110    lgetexpr '1'
2111  endtry
2112
2113  call assert_equal('1', getloclist(0)[0].text)
2114
2115  set efm&vim
2116endfunc
2117
2118func Test_caddbuffer_wrong()
2119  " This used to cause a memory access in freed memory.
2120  let save_efm = &efm
2121  set efm=%EEEE%m,%WWWW,%+CCCC%>%#,%GGGG%.#
2122  cgetexpr ['WWWW', 'EEEE', 'CCCC']
2123  let &efm = save_efm
2124  caddbuffer
2125  bwipe!
2126endfunc
2127
2128func Test_caddexpr_wrong()
2129  " This used to cause a memory access in freed memory.
2130  cbuffer
2131  cbuffer
2132  copen
2133  let save_efm = &efm
2134  set efm=%
2135  call assert_fails('caddexpr ""', 'E376:')
2136  let &efm = save_efm
2137endfunc
2138
2139func Test_dirstack_cleanup()
2140  " This used to cause a memory access in freed memory.
2141  let save_efm = &efm
2142  lexpr '0'
2143  lopen
2144  fun X(c)
2145    let save_efm=&efm
2146    set efm=%D%f
2147    if a:c == 'c'
2148      caddexpr '::'
2149    else
2150      laddexpr ':0:0'
2151    endif
2152    let &efm=save_efm
2153  endfun
2154  call X('c')
2155  call X('l')
2156  call setqflist([], 'r')
2157  caddbuffer
2158  let &efm = save_efm
2159endfunc
2160
2161" Tests for jumping to entries from the location list window and quickfix
2162" window
2163func Test_cwindow_jump()
2164  set efm=%f%%%l%%%m
2165  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2166  lopen | only
2167  lfirst
2168  call assert_true(winnr('$') == 2)
2169  call assert_true(winnr() == 1)
2170  " Location list for the new window should be set
2171  call assert_true(getloclist(0)[2].text == 'Line 30')
2172
2173  " Open a scratch buffer
2174  " Open a new window and create a location list
2175  " Open the location list window and close the other window
2176  " Jump to an entry.
2177  " Should create a new window and jump to the entry. The scrtach buffer
2178  " should not be used.
2179  enew | only
2180  set buftype=nofile
2181  below new
2182  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2183  lopen
2184  2wincmd c
2185  lnext
2186  call assert_true(winnr('$') == 3)
2187  call assert_true(winnr() == 2)
2188
2189  " Open two windows with two different location lists
2190  " Open the location list window and close the previous window
2191  " Jump to an entry in the location list window
2192  " Should open the file in the first window and not set the location list.
2193  enew | only
2194  lgetexpr ["F1%5%Line 5"]
2195  below new
2196  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2197  lopen
2198  2wincmd c
2199  lnext
2200  call assert_true(winnr() == 1)
2201  call assert_true(getloclist(0)[0].text == 'Line 5')
2202
2203  enew | only
2204  cgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2205  copen
2206  cnext
2207  call assert_true(winnr('$') == 2)
2208  call assert_true(winnr() == 1)
2209
2210  enew | only
2211  set efm&vim
2212endfunc
2213
2214func XvimgrepTests(cchar)
2215  call s:setup_commands(a:cchar)
2216
2217  call writefile(['Editor:VIM vim',
2218	      \ 'Editor:Emacs EmAcS',
2219	      \ 'Editor:Notepad NOTEPAD'], 'Xtestfile1')
2220  call writefile(['Linux', 'MacOS', 'MS-Windows'], 'Xtestfile2')
2221
2222  " Error cases
2223  call assert_fails('Xvimgrep /abc *', 'E682:')
2224
2225  let @/=''
2226  call assert_fails('Xvimgrep // *', 'E35:')
2227
2228  call assert_fails('Xvimgrep abc', 'E683:')
2229  call assert_fails('Xvimgrep a1b2c3 Xtestfile1', 'E480:')
2230  call assert_fails('Xvimgrep pat Xa1b2c3', 'E480:')
2231
2232  Xexpr ""
2233  Xvimgrepadd Notepad Xtestfile1
2234  Xvimgrepadd MacOS Xtestfile2
2235  let l = g:Xgetlist()
2236  call assert_equal(2, len(l))
2237  call assert_equal('Editor:Notepad NOTEPAD', l[0].text)
2238
2239  Xvimgrep #\cvim#g Xtestfile?
2240  let l = g:Xgetlist()
2241  call assert_equal(2, len(l))
2242  call assert_equal(8, l[0].col)
2243  call assert_equal(12, l[1].col)
2244
2245  1Xvimgrep ?Editor? Xtestfile*
2246  let l = g:Xgetlist()
2247  call assert_equal(1, len(l))
2248  call assert_equal('Editor:VIM vim', l[0].text)
2249
2250  edit +3 Xtestfile2
2251  Xvimgrep +\cemacs+j Xtestfile1
2252  let l = g:Xgetlist()
2253  call assert_equal('Xtestfile2', bufname(''))
2254  call assert_equal('Editor:Emacs EmAcS', l[0].text)
2255
2256  call delete('Xtestfile1')
2257  call delete('Xtestfile2')
2258endfunc
2259
2260" Tests for the :vimgrep command
2261func Test_vimgrep()
2262  call XvimgrepTests('c')
2263  call XvimgrepTests('l')
2264endfunc
2265
2266func XfreeTests(cchar)
2267  call s:setup_commands(a:cchar)
2268
2269  enew | only
2270
2271  " Deleting the quickfix stack should work even When the current list is
2272  " somewhere in the middle of the stack
2273  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2274  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2275  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2276  Xolder
2277  call g:Xsetlist([], 'f')
2278  call assert_equal(0, len(g:Xgetlist()))
2279
2280  " After deleting the stack, adding a new list should create a stack with a
2281  " single list.
2282  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2283  call assert_equal(1, g:Xgetlist({'all':1}).nr)
2284
2285  " Deleting the stack from a quickfix window should update/clear the
2286  " quickfix/location list window.
2287  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2288  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2289  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2290  Xolder
2291  Xwindow
2292  call g:Xsetlist([], 'f')
2293  call assert_equal(2, winnr('$'))
2294  call assert_equal(1, line('$'))
2295  Xclose
2296
2297  " Deleting the stack from a non-quickfix window should update/clear the
2298  " quickfix/location list window.
2299  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2300  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2301  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2302  Xolder
2303  Xwindow
2304  wincmd p
2305  call g:Xsetlist([], 'f')
2306  call assert_equal(0, len(g:Xgetlist()))
2307  wincmd p
2308  call assert_equal(2, winnr('$'))
2309  call assert_equal(1, line('$'))
2310
2311  " After deleting the location list stack, if the location list window is
2312  " opened, then a new location list should be created. So opening the
2313  " location list window again should not create a new window.
2314  if a:cchar == 'l'
2315      lexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2316      wincmd p
2317      lopen
2318      call assert_equal(2, winnr('$'))
2319  endif
2320  Xclose
2321endfunc
2322
2323" Tests for the quickifx free functionality
2324func Test_qf_free()
2325  call XfreeTests('c')
2326  call XfreeTests('l')
2327endfunc
2328
2329" Test for buffer overflow when parsing lines and adding new entries to
2330" the quickfix list.
2331func Test_bufoverflow()
2332  set efm=%f:%l:%m
2333  cgetexpr ['File1:100:' . repeat('x', 1025)]
2334
2335  set efm=%+GCompiler:\ %.%#,%f:%l:%m
2336  cgetexpr ['Compiler: ' . repeat('a', 1015), 'File1:10:Hello World']
2337
2338  set efm=%DEntering\ directory\ %f,%f:%l:%m
2339  cgetexpr ['Entering directory ' . repeat('a', 1006),
2340	      \ 'File1:10:Hello World']
2341  set efm&vim
2342endfunc
2343
2344" Tests for getting the quickfix stack size
2345func XsizeTests(cchar)
2346  call s:setup_commands(a:cchar)
2347
2348  call g:Xsetlist([], 'f')
2349  call assert_equal(0, g:Xgetlist({'nr':'$'}).nr)
2350  call assert_equal(1, len(g:Xgetlist({'nr':'$', 'all':1})))
2351  call assert_equal(0, len(g:Xgetlist({'nr':0})))
2352
2353  Xexpr "File1:10:Line1"
2354  Xexpr "File2:20:Line2"
2355  Xexpr "File3:30:Line3"
2356  Xolder | Xolder
2357  call assert_equal(3, g:Xgetlist({'nr':'$'}).nr)
2358  call g:Xsetlist([], 'f')
2359
2360  Xexpr "File1:10:Line1"
2361  Xexpr "File2:20:Line2"
2362  Xexpr "File3:30:Line3"
2363  Xolder | Xolder
2364  call g:Xsetlist([], 'a', {'nr':'$', 'title':'Compiler'})
2365  call assert_equal('Compiler', g:Xgetlist({'nr':3, 'all':1}).title)
2366endfunc
2367
2368func Test_Qf_Size()
2369  call XsizeTests('c')
2370  call XsizeTests('l')
2371endfunc
2372
2373func Test_cclose_from_copen()
2374    augroup QF_Test
2375	au!
2376        au FileType qf :call assert_fails(':cclose', 'E788')
2377    augroup END
2378    copen
2379    augroup QF_Test
2380	au!
2381    augroup END
2382    augroup! QF_Test
2383endfunc
2384
2385func Test_cclose_in_autocmd()
2386  " Problem is only triggered if "starting" is zero, so that the OptionsSet
2387  " event will be triggered.
2388  call test_override('starting', 1)
2389  augroup QF_Test
2390    au!
2391    au FileType qf :call assert_fails(':cclose', 'E788')
2392  augroup END
2393  copen
2394  augroup QF_Test
2395    au!
2396  augroup END
2397  augroup! QF_Test
2398  call test_override('starting', 0)
2399endfunc
2400
2401func Test_resize_from_copen()
2402    augroup QF_Test
2403	au!
2404        au FileType qf resize 5
2405    augroup END
2406    try
2407	" This should succeed without any exception.  No other buffers are
2408	" involved in the autocmd.
2409	copen
2410    finally
2411	augroup QF_Test
2412	    au!
2413	augroup END
2414	augroup! QF_Test
2415    endtry
2416endfunc
2417
2418" Tests for the quickfix buffer b:changedtick variable
2419func Xchangedtick_tests(cchar)
2420  call s:setup_commands(a:cchar)
2421
2422  new | only
2423
2424  Xexpr "" | Xexpr "" | Xexpr ""
2425
2426  Xopen
2427  Xolder
2428  Xolder
2429  Xaddexpr "F1:10:Line10"
2430  Xaddexpr "F2:20:Line20"
2431  call g:Xsetlist([{"filename":"F3", "lnum":30, "text":"Line30"}], 'a')
2432  call g:Xsetlist([], 'f')
2433  call assert_equal(8, getbufvar('%', 'changedtick'))
2434  Xclose
2435endfunc
2436
2437func Test_changedtick()
2438  call Xchangedtick_tests('c')
2439  call Xchangedtick_tests('l')
2440endfunc
2441
2442" Tests for parsing an expression using setqflist()
2443func Xsetexpr_tests(cchar)
2444  call s:setup_commands(a:cchar)
2445
2446  let t = ["File1:10:Line10", "File1:20:Line20"]
2447  call g:Xsetlist([], ' ', {'lines' : t})
2448  call g:Xsetlist([], 'a', {'lines' : ["File1:30:Line30"]})
2449
2450  let l = g:Xgetlist()
2451  call assert_equal(3, len(l))
2452  call assert_equal(20, l[1].lnum)
2453  call assert_equal('Line30', l[2].text)
2454  call g:Xsetlist([], 'r', {'lines' : ["File2:5:Line5"]})
2455  let l = g:Xgetlist()
2456  call assert_equal(1, len(l))
2457  call assert_equal('Line5', l[0].text)
2458  call assert_equal(-1, g:Xsetlist([], 'a', {'lines' : 10}))
2459  call assert_equal(-1, g:Xsetlist([], 'a', {'lines' : "F1:10:L10"}))
2460
2461  call g:Xsetlist([], 'f')
2462  " Add entries to multiple lists
2463  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["File1:10:Line10"]})
2464  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["File2:20:Line20"]})
2465  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["File1:15:Line15"]})
2466  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["File2:25:Line25"]})
2467  call assert_equal('Line15', g:Xgetlist({'nr':1, 'items':1}).items[1].text)
2468  call assert_equal('Line25', g:Xgetlist({'nr':2, 'items':1}).items[1].text)
2469
2470  " Adding entries using a custom efm
2471  set efm&
2472  call g:Xsetlist([], ' ', {'efm' : '%f#%l#%m',
2473				\ 'lines' : ["F1#10#L10", "F2#20#L20"]})
2474  call assert_equal(20, g:Xgetlist({'items':1}).items[1].lnum)
2475  call g:Xsetlist([], 'a', {'efm' : '%f#%l#%m', 'lines' : ["F3:30:L30"]})
2476  call assert_equal('F3:30:L30', g:Xgetlist({'items':1}).items[2].text)
2477  call assert_equal(20, g:Xgetlist({'items':1}).items[1].lnum)
2478  call assert_equal(-1, g:Xsetlist([], 'a', {'efm' : [],
2479				\ 'lines' : ['F1:10:L10']}))
2480endfunc
2481
2482func Test_setexpr()
2483  call Xsetexpr_tests('c')
2484  call Xsetexpr_tests('l')
2485endfunc
2486
2487" Tests for per quickfix/location list directory stack
2488func Xmultidirstack_tests(cchar)
2489  call s:setup_commands(a:cchar)
2490
2491  call g:Xsetlist([], 'f')
2492  Xexpr "" | Xexpr ""
2493
2494  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["Entering dir 'Xone/a'"]})
2495  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["Entering dir 'Xtwo/a'"]})
2496  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["one.txt:3:one one one"]})
2497  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["two.txt:5:two two two"]})
2498
2499  let l1 = g:Xgetlist({'nr':1, 'items':1})
2500  let l2 = g:Xgetlist({'nr':2, 'items':1})
2501  call assert_equal('Xone/a/one.txt', bufname(l1.items[1].bufnr))
2502  call assert_equal(3, l1.items[1].lnum)
2503  call assert_equal('Xtwo/a/two.txt', bufname(l2.items[1].bufnr))
2504  call assert_equal(5, l2.items[1].lnum)
2505endfunc
2506
2507func Test_multidirstack()
2508  call mkdir('Xone/a', 'p')
2509  call mkdir('Xtwo/a', 'p')
2510  let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7']
2511  call writefile(lines, 'Xone/a/one.txt')
2512  call writefile(lines, 'Xtwo/a/two.txt')
2513  let save_efm = &efm
2514  set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f'
2515
2516  call Xmultidirstack_tests('c')
2517  call Xmultidirstack_tests('l')
2518
2519  let &efm = save_efm
2520  call delete('Xone', 'rf')
2521  call delete('Xtwo', 'rf')
2522endfunc
2523
2524" Tests for per quickfix/location list file stack
2525func Xmultifilestack_tests(cchar)
2526  call s:setup_commands(a:cchar)
2527
2528  call g:Xsetlist([], 'f')
2529  Xexpr "" | Xexpr ""
2530
2531  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["[one.txt]"]})
2532  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["[two.txt]"]})
2533  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["(3,5) one one one"]})
2534  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["(5,9) two two two"]})
2535
2536  let l1 = g:Xgetlist({'nr':1, 'items':1})
2537  let l2 = g:Xgetlist({'nr':2, 'items':1})
2538  call assert_equal('one.txt', bufname(l1.items[1].bufnr))
2539  call assert_equal(3, l1.items[1].lnum)
2540  call assert_equal('two.txt', bufname(l2.items[1].bufnr))
2541  call assert_equal(5, l2.items[1].lnum)
2542endfunc
2543
2544func Test_multifilestack()
2545  let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7']
2546  call writefile(lines, 'one.txt')
2547  call writefile(lines, 'two.txt')
2548  let save_efm = &efm
2549  set efm=%+P[%f],(%l\\,%c)\ %m,%-Q
2550
2551  call Xmultifilestack_tests('c')
2552  call Xmultifilestack_tests('l')
2553
2554  let &efm = save_efm
2555  call delete('one.txt')
2556  call delete('two.txt')
2557endfunc
2558
2559" Tests for per buffer 'efm' setting
2560func Test_perbuf_efm()
2561  call writefile(["File1-10-Line10"], 'one.txt')
2562  call writefile(["File2#20#Line20"], 'two.txt')
2563  set efm=%f#%l#%m
2564  new | only
2565  new
2566  setlocal efm=%f-%l-%m
2567  cfile one.txt
2568  wincmd w
2569  caddfile two.txt
2570
2571  let l = getqflist()
2572  call assert_equal(10, l[0].lnum)
2573  call assert_equal('Line20', l[1].text)
2574
2575  set efm&
2576  new | only
2577  call delete('one.txt')
2578  call delete('two.txt')
2579endfunc
2580
2581" Open multiple help windows using ":lhelpgrep
2582" This test used to crash Vim
2583func Test_Multi_LL_Help()
2584    new | only
2585    lhelpgrep window
2586    lopen
2587    e#
2588    lhelpgrep buffer
2589    call assert_equal(3, winnr('$'))
2590    call assert_true(len(getloclist(1)) != 0)
2591    call assert_true(len(getloclist(2)) != 0)
2592    new | only
2593endfunc
2594
2595" Tests for adding new quickfix lists using setqflist()
2596func XaddQf_tests(cchar)
2597  call s:setup_commands(a:cchar)
2598
2599  " Create a new list using ' ' for action
2600  call g:Xsetlist([], 'f')
2601  call g:Xsetlist([], ' ', {'title' : 'Test1'})
2602  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2603  call assert_equal(1, l.nr)
2604  call assert_equal('Test1', l.title)
2605
2606  " Create a new list using ' ' for action and '$' for 'nr'
2607  call g:Xsetlist([], 'f')
2608  call g:Xsetlist([], ' ', {'title' : 'Test2', 'nr' : '$'})
2609  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2610  call assert_equal(1, l.nr)
2611  call assert_equal('Test2', l.title)
2612
2613  " Create a new list using 'a' for action
2614  call g:Xsetlist([], 'f')
2615  call g:Xsetlist([], 'a', {'title' : 'Test3'})
2616  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2617  call assert_equal(1, l.nr)
2618  call assert_equal('Test3', l.title)
2619
2620  " Create a new list using 'a' for action and '$' for 'nr'
2621  call g:Xsetlist([], 'f')
2622  call g:Xsetlist([], 'a', {'title' : 'Test3', 'nr' : '$'})
2623  call g:Xsetlist([], 'a', {'title' : 'Test4'})
2624  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2625  call assert_equal(1, l.nr)
2626  call assert_equal('Test4', l.title)
2627
2628  " Adding a quickfix list should remove all the lists following the current
2629  " list.
2630  Xexpr "" | Xexpr "" | Xexpr ""
2631  silent! 10Xolder
2632  call g:Xsetlist([], ' ', {'title' : 'Test5'})
2633  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2634  call assert_equal(2, l.nr)
2635  call assert_equal('Test5', l.title)
2636
2637  " Add a quickfix list using '$' as the list number.
2638  let lastqf = g:Xgetlist({'nr':'$'}).nr
2639  silent! 99Xolder
2640  call g:Xsetlist([], ' ', {'nr' : '$', 'title' : 'Test6'})
2641  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2642  call assert_equal(lastqf + 1, l.nr)
2643  call assert_equal('Test6', l.title)
2644
2645  " Add a quickfix list using 'nr' set to one more than the quickfix
2646  " list size.
2647  let lastqf = g:Xgetlist({'nr':'$'}).nr
2648  silent! 99Xolder
2649  call g:Xsetlist([], ' ', {'nr' : lastqf + 1, 'title' : 'Test7'})
2650  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2651  call assert_equal(lastqf + 1, l.nr)
2652  call assert_equal('Test7', l.title)
2653
2654  " Add a quickfix list to a stack with 10 lists using 'nr' set to '$'
2655  exe repeat('Xexpr "" |', 9) . 'Xexpr ""'
2656  silent! 99Xolder
2657  call g:Xsetlist([], ' ', {'nr' : '$', 'title' : 'Test8'})
2658  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2659  call assert_equal(10, l.nr)
2660  call assert_equal('Test8', l.title)
2661
2662  " Add a quickfix list using 'nr' set to a value greater than 10
2663  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : 12, 'title' : 'Test9'}))
2664
2665  " Try adding a quickfix list with 'nr' set to a value greater than the
2666  " quickfix list size but less than 10.
2667  call g:Xsetlist([], 'f')
2668  Xexpr "" | Xexpr "" | Xexpr ""
2669  silent! 99Xolder
2670  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : 8, 'title' : 'Test10'}))
2671
2672  " Add a quickfix list using 'nr' set to a some string or list
2673  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : [1,2], 'title' : 'Test11'}))
2674endfunc
2675
2676func Test_add_qf()
2677  call XaddQf_tests('c')
2678  call XaddQf_tests('l')
2679endfunc
2680
2681" Test for getting the quickfix list items from some text without modifying
2682" the quickfix stack
2683func XgetListFromLines(cchar)
2684  call s:setup_commands(a:cchar)
2685  call g:Xsetlist([], 'f')
2686
2687  let l = g:Xgetlist({'lines' : ["File2:20:Line20", "File2:30:Line30"]}).items
2688  call assert_equal(2, len(l))
2689  call assert_equal(30, l[1].lnum)
2690
2691  call assert_equal({}, g:Xgetlist({'lines' : 10}))
2692  call assert_equal({}, g:Xgetlist({'lines' : 'File1:10:Line10'}))
2693  call assert_equal([], g:Xgetlist({'lines' : []}).items)
2694  call assert_equal([], g:Xgetlist({'lines' : [10, 20]}).items)
2695
2696  " Parse text using a custom efm
2697  set efm&
2698  let l = g:Xgetlist({'lines':['File3#30#Line30'], 'efm' : '%f#%l#%m'}).items
2699  call assert_equal('Line30', l[0].text)
2700  let l = g:Xgetlist({'lines':['File3:30:Line30'], 'efm' : '%f-%l-%m'}).items
2701  call assert_equal('File3:30:Line30', l[0].text)
2702  let l = g:Xgetlist({'lines':['File3:30:Line30'], 'efm' : [1,2]})
2703  call assert_equal({}, l)
2704  call assert_fails("call g:Xgetlist({'lines':['abc'], 'efm':'%2'})", 'E376:')
2705  call assert_fails("call g:Xgetlist({'lines':['abc'], 'efm':''})", 'E378:')
2706
2707  " Make sure that the quickfix stack is not modified
2708  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
2709endfunc
2710
2711func Test_get_list_from_lines()
2712  call XgetListFromLines('c')
2713  call XgetListFromLines('l')
2714endfunc
2715
2716" Tests for the quickfix list id
2717func Xqfid_tests(cchar)
2718  call s:setup_commands(a:cchar)
2719
2720  call g:Xsetlist([], 'f')
2721  call assert_equal({}, g:Xgetlist({'id':0}))
2722  Xexpr ''
2723  let start_id = g:Xgetlist({'id' : 0}).id
2724  Xexpr '' | Xexpr ''
2725  Xolder
2726  call assert_equal(start_id, g:Xgetlist({'id':0, 'nr':1}).id)
2727  call assert_equal(start_id + 1, g:Xgetlist({'id':0, 'nr':0}).id)
2728  call assert_equal(start_id + 2, g:Xgetlist({'id':0, 'nr':'$'}).id)
2729  call assert_equal({}, g:Xgetlist({'id':0, 'nr':99}))
2730  call assert_equal(2, g:Xgetlist({'id':start_id + 1, 'nr':0}).nr)
2731  call assert_equal({}, g:Xgetlist({'id':99, 'nr':0}))
2732  call assert_equal({}, g:Xgetlist({'id':"abc", 'nr':0}))
2733
2734  call g:Xsetlist([], 'a', {'id':start_id, 'context':[1,2]})
2735  call assert_equal([1,2], g:Xgetlist({'nr':1, 'context':1}).context)
2736  call g:Xsetlist([], 'a', {'id':start_id+1, 'lines':['F1:10:L10']})
2737  call assert_equal('L10', g:Xgetlist({'nr':2, 'items':1}).items[0].text)
2738  call assert_equal(-1, g:Xsetlist([], 'a', {'id':999, 'title':'Vim'}))
2739  call assert_equal(-1, g:Xsetlist([], 'a', {'id':'abc', 'title':'Vim'}))
2740
2741  let qfid = g:Xgetlist({'id':0, 'nr':0})
2742  call g:Xsetlist([], 'f')
2743  call assert_equal({}, g:Xgetlist({'id':qfid, 'nr':0}))
2744endfunc
2745
2746func Test_qf_id()
2747  call Xqfid_tests('c')
2748  call Xqfid_tests('l')
2749endfunc
2750