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 -range Xnfile <mods><count>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    command! -nargs=0 -count Xcc <count>cc
40    let g:Xgetlist = function('getqflist')
41    let g:Xsetlist = function('setqflist')
42    call setqflist([], 'f')
43  else
44    command! -nargs=* -bang Xlist <mods>llist<bang> <args>
45    command! -nargs=* Xgetexpr <mods>lgetexpr <args>
46    command! -nargs=* Xaddexpr <mods>laddexpr <args>
47    command! -nargs=* -count Xolder <mods><count>lolder <args>
48    command! -nargs=* Xnewer <mods>lnewer <args>
49    command! -nargs=* Xopen <mods>lopen <args>
50    command! -nargs=* Xwindow <mods>lwindow <args>
51    command! -nargs=* Xbottom <mods>lbottom <args>
52    command! -nargs=* Xclose <mods>lclose <args>
53    command! -nargs=* -bang Xfile <mods>lfile<bang> <args>
54    command! -nargs=* Xgetfile <mods>lgetfile <args>
55    command! -nargs=* Xaddfile <mods>laddfile <args>
56    command! -nargs=* -bang Xbuffer <mods>lbuffer<bang> <args>
57    command! -nargs=* Xgetbuffer <mods>lgetbuffer <args>
58    command! -nargs=* Xaddbuffer <mods>laddbuffer <args>
59    command! -nargs=* Xrewind <mods>lrewind <args>
60    command! -count -nargs=* -bang Xnext <mods><count>lnext<bang> <args>
61    command! -count -nargs=* -bang Xprev <mods><count>lprev<bang> <args>
62    command! -nargs=* -bang Xfirst <mods>lfirst<bang> <args>
63    command! -nargs=* -bang Xlast <mods>llast<bang> <args>
64    command! -nargs=* -bang -range Xnfile <mods><count>lnfile<bang> <args>
65    command! -nargs=* -bang Xpfile <mods>lpfile<bang> <args>
66    command! -nargs=* Xexpr <mods>lexpr <args>
67    command! -range -nargs=* Xvimgrep <mods><count>lvimgrep <args>
68    command! -nargs=* Xvimgrepadd <mods>lvimgrepadd <args>
69    command! -nargs=* Xgrep <mods> lgrep <args>
70    command! -nargs=* Xgrepadd <mods> lgrepadd <args>
71    command! -nargs=* Xhelpgrep lhelpgrep <args>
72    command! -nargs=0 -count Xcc <count>ll
73    let g:Xgetlist = function('getloclist', [0])
74    let g:Xsetlist = function('setloclist', [0])
75    call setloclist(0, [], 'f')
76  endif
77endfunc
78
79" Tests for the :clist and :llist commands
80func XlistTests(cchar)
81  call s:setup_commands(a:cchar)
82
83  if a:cchar == 'l'
84      call assert_fails('llist', 'E776:')
85  endif
86  " With an empty list, command should return error
87  Xgetexpr []
88  silent! Xlist
89  call assert_true(v:errmsg ==# 'E42: No Errors')
90
91  " Populate the list and then try
92  Xgetexpr ['non-error 1', 'Xtestfile1:1:3:Line1',
93		  \ 'non-error 2', 'Xtestfile2:2:2:Line2',
94		  \ 'non-error 3', 'Xtestfile3:3:1:Line3']
95
96  " List only valid entries
97  let l = split(execute('Xlist', ''), "\n")
98  call assert_equal([' 2 Xtestfile1:1 col 3: Line1',
99		   \ ' 4 Xtestfile2:2 col 2: Line2',
100		   \ ' 6 Xtestfile3:3 col 1: Line3'], l)
101
102  " List all the entries
103  let l = split(execute('Xlist!', ''), "\n")
104  call assert_equal([' 1: non-error 1', ' 2 Xtestfile1:1 col 3: Line1',
105		   \ ' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2',
106		   \ ' 5: non-error 3', ' 6 Xtestfile3:3 col 1: Line3'], l)
107
108  " List a range of errors
109  let l = split(execute('Xlist 3,6', ''), "\n")
110  call assert_equal([' 4 Xtestfile2:2 col 2: Line2',
111		   \ ' 6 Xtestfile3:3 col 1: Line3'], l)
112
113  let l = split(execute('Xlist! 3,4', ''), "\n")
114  call assert_equal([' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2'], l)
115
116  let l = split(execute('Xlist -6,-4', ''), "\n")
117  call assert_equal([' 2 Xtestfile1:1 col 3: Line1'], l)
118
119  let l = split(execute('Xlist! -5,-3', ''), "\n")
120  call assert_equal([' 2 Xtestfile1:1 col 3: Line1',
121		   \ ' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2'], l)
122
123  " Test for '+'
124  let l = split(execute('Xlist! +2', ''), "\n")
125  call assert_equal([' 2 Xtestfile1:1 col 3: Line1',
126		   \ ' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2'], l)
127
128  " Different types of errors
129  call g:Xsetlist([{'lnum':10,'col':5,'type':'W', 'text':'Warning','nr':11},
130	      \ {'lnum':20,'col':10,'type':'e','text':'Error','nr':22},
131	      \ {'lnum':30,'col':15,'type':'i','text':'Info','nr':33},
132	      \ {'lnum':40,'col':20,'type':'x', 'text':'Other','nr':44},
133	      \ {'lnum':50,'col':25,'type':"\<C-A>",'text':'one','nr':55}])
134  let l = split(execute('Xlist', ""), "\n")
135  call assert_equal([' 1:10 col 5 warning  11: Warning',
136	      \ ' 2:20 col 10 error  22: Error',
137	      \ ' 3:30 col 15 info  33: Info',
138	      \ ' 4:40 col 20 x  44: Other',
139	      \ ' 5:50 col 25  55: one'], l)
140
141  " Error cases
142  call assert_fails('Xlist abc', 'E488:')
143endfunc
144
145func Test_clist()
146  call XlistTests('c')
147  call XlistTests('l')
148endfunc
149
150" Tests for the :colder, :cnewer, :lolder and :lnewer commands
151" Note that this test assumes that a quickfix/location list is
152" already set by the caller.
153func XageTests(cchar)
154  call s:setup_commands(a:cchar)
155
156  let list = [{'bufnr': bufnr('%'), 'lnum': 1}]
157  call g:Xsetlist(list)
158
159  " Jumping to a non existent list should return error
160  silent! Xolder 99
161  call assert_true(v:errmsg ==# 'E380: At bottom of quickfix stack')
162
163  silent! Xnewer 99
164  call assert_true(v:errmsg ==# 'E381: At top of quickfix stack')
165
166  " Add three quickfix/location lists
167  Xgetexpr ['Xtestfile1:1:3:Line1']
168  Xgetexpr ['Xtestfile2:2:2:Line2']
169  Xgetexpr ['Xtestfile3:3:1:Line3']
170
171  " Go back two lists
172  Xolder
173  let l = g:Xgetlist()
174  call assert_equal('Line2', l[0].text)
175
176  " Go forward two lists
177  Xnewer
178  let l = g:Xgetlist()
179  call assert_equal('Line3', l[0].text)
180
181  " Test for the optional count argument
182  Xolder 2
183  let l = g:Xgetlist()
184  call assert_equal('Line1', l[0].text)
185
186  Xnewer 2
187  let l = g:Xgetlist()
188  call assert_equal('Line3', l[0].text)
189endfunc
190
191func Test_cage()
192  call XageTests('c')
193  call XageTests('l')
194endfunc
195
196" Tests for the :cwindow, :lwindow :cclose, :lclose, :copen and :lopen
197" commands
198func XwindowTests(cchar)
199  call s:setup_commands(a:cchar)
200
201  " Opening the location list window without any errors should fail
202  if a:cchar == 'l'
203      call assert_fails('lopen', 'E776:')
204  endif
205
206  " Create a list with no valid entries
207  Xgetexpr ['non-error 1', 'non-error 2', 'non-error 3']
208
209  " Quickfix/Location window should not open with no valid errors
210  Xwindow
211  call assert_true(winnr('$') == 1)
212
213  " Create a list with valid entries
214  Xgetexpr ['Xtestfile1:1:3:Line1', 'Xtestfile2:2:2:Line2',
215		  \ 'Xtestfile3:3:1:Line3']
216
217  " Open the window
218  Xwindow
219  call assert_true(winnr('$') == 2 && winnr() == 2 &&
220	\ getline('.') ==# 'Xtestfile1|1 col 3| Line1')
221  redraw!
222
223  " Close the window
224  Xclose
225  call assert_true(winnr('$') == 1)
226
227  " Create a list with no valid entries
228  Xgetexpr ['non-error 1', 'non-error 2', 'non-error 3']
229
230  " Open the window
231  Xopen 5
232  call assert_true(winnr('$') == 2 && getline('.') ==# '|| non-error 1'
233		      \  && winheight('.') == 5)
234
235  " Opening the window again, should move the cursor to that window
236  wincmd t
237  Xopen 7
238  call assert_true(winnr('$') == 2 && winnr() == 2 &&
239	\ winheight('.') == 7 &&
240	\ getline('.') ==# '|| non-error 1')
241
242
243  " Calling cwindow should close the quickfix window with no valid errors
244  Xwindow
245  call assert_true(winnr('$') == 1)
246
247  if a:cchar == 'c'
248      " Opening the quickfix window in multiple tab pages should reuse the
249      " quickfix buffer
250      Xgetexpr ['Xtestfile1:1:3:Line1', 'Xtestfile2:2:2:Line2',
251		  \ 'Xtestfile3:3:1:Line3']
252      Xopen
253      let qfbufnum = bufnr('%')
254      tabnew
255      Xopen
256      call assert_equal(qfbufnum, bufnr('%'))
257      new | only | tabonly
258  endif
259endfunc
260
261func Test_cwindow()
262  call XwindowTests('c')
263  call XwindowTests('l')
264endfunc
265
266" Tests for the :cfile, :lfile, :caddfile, :laddfile, :cgetfile and :lgetfile
267" commands.
268func XfileTests(cchar)
269  call s:setup_commands(a:cchar)
270
271  call writefile(['Xtestfile1:700:10:Line 700',
272	\ 'Xtestfile2:800:15:Line 800'], 'Xqftestfile1')
273
274  enew!
275  Xfile Xqftestfile1
276  let l = g:Xgetlist()
277  call assert_true(len(l) == 2 &&
278	\ l[0].lnum == 700 && l[0].col == 10 && l[0].text ==# 'Line 700' &&
279	\ l[1].lnum == 800 && l[1].col == 15 && l[1].text ==# 'Line 800')
280
281  " Test with a non existent file
282  call assert_fails('Xfile non_existent_file', 'E40')
283
284  " Run cfile/lfile from a modified buffer
285  enew!
286  silent! put ='Quickfix'
287  silent! Xfile Xqftestfile1
288  call assert_true(v:errmsg ==# 'E37: No write since last change (add ! to override)')
289
290  call writefile(['Xtestfile3:900:30:Line 900'], 'Xqftestfile1')
291  Xaddfile Xqftestfile1
292  let l = g:Xgetlist()
293  call assert_true(len(l) == 3 &&
294	\ l[2].lnum == 900 && l[2].col == 30 && l[2].text ==# 'Line 900')
295
296  call writefile(['Xtestfile1:222:77:Line 222',
297	\ 'Xtestfile2:333:88:Line 333'], 'Xqftestfile1')
298
299  enew!
300  Xgetfile Xqftestfile1
301  let l = g:Xgetlist()
302  call assert_true(len(l) == 2 &&
303	\ l[0].lnum == 222 && l[0].col == 77 && l[0].text ==# 'Line 222' &&
304	\ l[1].lnum == 333 && l[1].col == 88 && l[1].text ==# 'Line 333')
305
306  call delete('Xqftestfile1')
307endfunc
308
309func Test_cfile()
310  call XfileTests('c')
311  call XfileTests('l')
312endfunc
313
314" Tests for the :cbuffer, :lbuffer, :caddbuffer, :laddbuffer, :cgetbuffer and
315" :lgetbuffer commands.
316func XbufferTests(cchar)
317  call s:setup_commands(a:cchar)
318
319  enew!
320  silent! call setline(1, ['Xtestfile7:700:10:Line 700',
321	\ 'Xtestfile8:800:15:Line 800'])
322  Xbuffer!
323  let l = g:Xgetlist()
324  call assert_true(len(l) == 2 &&
325	\ l[0].lnum == 700 && l[0].col == 10 && l[0].text ==# 'Line 700' &&
326	\ l[1].lnum == 800 && l[1].col == 15 && l[1].text ==# 'Line 800')
327
328  enew!
329  silent! call setline(1, ['Xtestfile9:900:55:Line 900',
330	\ 'Xtestfile10:950:66:Line 950'])
331  Xgetbuffer
332  let l = g:Xgetlist()
333  call assert_true(len(l) == 2 &&
334	\ l[0].lnum == 900 && l[0].col == 55 && l[0].text ==# 'Line 900' &&
335	\ l[1].lnum == 950 && l[1].col == 66 && l[1].text ==# 'Line 950')
336
337  enew!
338  silent! call setline(1, ['Xtestfile11:700:20:Line 700',
339	\ 'Xtestfile12:750:25:Line 750'])
340  Xaddbuffer
341  let l = g:Xgetlist()
342  call assert_true(len(l) == 4 &&
343	\ l[1].lnum == 950 && l[1].col == 66 && l[1].text ==# 'Line 950' &&
344	\ l[2].lnum == 700 && l[2].col == 20 && l[2].text ==# 'Line 700' &&
345	\ l[3].lnum == 750 && l[3].col == 25 && l[3].text ==# 'Line 750')
346  enew!
347
348  " Check for invalid buffer
349  call assert_fails('Xbuffer 199', 'E474:')
350
351  " Check for unloaded buffer
352  edit Xtestfile1
353  let bnr = bufnr('%')
354  enew!
355  call assert_fails('Xbuffer ' . bnr, 'E681:')
356
357  " Check for invalid range
358  " Using Xbuffer will not run the range check in the cbuffer/lbuffer
359  " commands. So directly call the commands.
360  if (a:cchar == 'c')
361      call assert_fails('900,999cbuffer', 'E16:')
362  else
363      call assert_fails('900,999lbuffer', 'E16:')
364  endif
365endfunc
366
367func Test_cbuffer()
368  call XbufferTests('c')
369  call XbufferTests('l')
370endfunc
371
372func XexprTests(cchar)
373  call s:setup_commands(a:cchar)
374
375  call assert_fails('Xexpr 10', 'E777:')
376endfunc
377
378func Test_cexpr()
379  call XexprTests('c')
380  call XexprTests('l')
381endfunc
382
383" Tests for :cnext, :cprev, :cfirst, :clast commands
384func Xtest_browse(cchar)
385  call s:setup_commands(a:cchar)
386
387  call g:Xsetlist([], 'f')
388  " Jumping to first or next location list entry without any error should
389  " result in failure
390  if a:cchar == 'c'
391    let err = 'E42:'
392  else
393    let err = 'E776:'
394  endif
395  call assert_fails('Xnext', err)
396  call assert_fails('Xprev', err)
397  call assert_fails('Xnfile', err)
398  call assert_fails('Xpfile', err)
399
400  call s:create_test_file('Xqftestfile1')
401  call s:create_test_file('Xqftestfile2')
402
403  Xgetexpr ['Xqftestfile1:5:Line5',
404		\ 'Xqftestfile1:6:Line6',
405		\ 'Xqftestfile2:10:Line10',
406		\ 'Xqftestfile2:11:Line11',
407		\ 'RegularLine1',
408		\ 'RegularLine2']
409
410  Xfirst
411  call assert_fails('Xprev', 'E553')
412  call assert_fails('Xpfile', 'E553')
413  Xnfile
414  call assert_equal('Xqftestfile2', bufname('%'))
415  call assert_equal(10, line('.'))
416  Xpfile
417  call assert_equal('Xqftestfile1', bufname('%'))
418  call assert_equal(6, line('.'))
419  5Xcc
420  call assert_equal(5, g:Xgetlist({'idx':0}).idx)
421  2Xcc
422  call assert_equal(2, g:Xgetlist({'idx':0}).idx)
423  10Xcc
424  call assert_equal(6, g:Xgetlist({'idx':0}).idx)
425  Xlast
426  Xprev
427  call assert_equal('Xqftestfile2', bufname('%'))
428  call assert_equal(11, line('.'))
429  call assert_fails('Xnext', 'E553')
430  call assert_fails('Xnfile', 'E553')
431  Xrewind
432  call assert_equal('Xqftestfile1', bufname('%'))
433  call assert_equal(5, line('.'))
434
435  10Xnext
436  call assert_equal('Xqftestfile2', bufname('%'))
437  call assert_equal(11, line('.'))
438  10Xprev
439  call assert_equal('Xqftestfile1', bufname('%'))
440  call assert_equal(5, line('.'))
441
442  " Jumping to an error from the error window using cc command
443  Xgetexpr ['Xqftestfile1:5:Line5',
444		\ 'Xqftestfile1:6:Line6',
445		\ 'Xqftestfile2:10:Line10',
446		\ 'Xqftestfile2:11:Line11']
447  Xopen
448  10Xcc
449  call assert_equal(11, line('.'))
450  call assert_equal('Xqftestfile2', bufname('%'))
451
452  " Jumping to an error from the error window (when only the error window is
453  " present)
454  Xopen | only
455  Xlast 1
456  call assert_equal(5, line('.'))
457  call assert_equal('Xqftestfile1', bufname('%'))
458
459  Xexpr ""
460  call assert_fails('Xnext', 'E42:')
461
462  call delete('Xqftestfile1')
463  call delete('Xqftestfile2')
464
465  " Should be able to use next/prev with invalid entries
466  Xexpr ""
467  call assert_equal(0, g:Xgetlist({'idx' : 0}).idx)
468  call assert_equal(0, g:Xgetlist({'size' : 0}).size)
469  Xaddexpr ['foo', 'bar', 'baz', 'quux', 'shmoo']
470  call assert_equal(5, g:Xgetlist({'size' : 0}).size)
471  Xlast
472  call assert_equal(5, g:Xgetlist({'idx' : 0}).idx)
473  Xfirst
474  call assert_equal(1, g:Xgetlist({'idx' : 0}).idx)
475  2Xnext
476  call assert_equal(3, g:Xgetlist({'idx' : 0}).idx)
477endfunc
478
479func Test_browse()
480  call Xtest_browse('c')
481  call Xtest_browse('l')
482endfunc
483
484func Test_nomem()
485  call test_alloc_fail(GetAllocId('qf_dirname_start'), 0, 0)
486  call assert_fails('vimgrep vim runtest.vim', 'E342:')
487
488  call test_alloc_fail(GetAllocId('qf_dirname_now'), 0, 0)
489  call assert_fails('vimgrep vim runtest.vim', 'E342:')
490
491  call test_alloc_fail(GetAllocId('qf_namebuf'), 0, 0)
492  call assert_fails('cfile runtest.vim', 'E342:')
493
494  call test_alloc_fail(GetAllocId('qf_errmsg'), 0, 0)
495  call assert_fails('cfile runtest.vim', 'E342:')
496
497  call test_alloc_fail(GetAllocId('qf_pattern'), 0, 0)
498  call assert_fails('cfile runtest.vim', 'E342:')
499
500endfunc
501
502func s:test_xhelpgrep(cchar)
503  call s:setup_commands(a:cchar)
504  Xhelpgrep quickfix
505  Xopen
506  if a:cchar == 'c'
507    let title_text = ':helpgrep quickfix'
508  else
509    let title_text = ':lhelpgrep quickfix'
510  endif
511  call assert_true(w:quickfix_title =~ title_text, w:quickfix_title)
512
513  " Jumping to a help topic should open the help window
514  only
515  Xnext
516  call assert_true(&buftype == 'help')
517  call assert_true(winnr('$') == 2)
518  " Jumping to the next match should reuse the help window
519  Xnext
520  call assert_true(&buftype == 'help')
521  call assert_true(winnr() == 1)
522  call assert_true(winnr('$') == 2)
523  " Jumping to the next match from the quickfix window should reuse the help
524  " window
525  Xopen
526  Xnext
527  call assert_true(&buftype == 'help')
528  call assert_true(winnr() == 1)
529  call assert_true(winnr('$') == 2)
530
531  " This wipes out the buffer, make sure that doesn't cause trouble.
532  Xclose
533
534  if a:cchar == 'l'
535      " When a help window is present, running :lhelpgrep should reuse the
536      " help window and not the current window
537      new | only
538      call g:Xsetlist([], 'f')
539      help index.txt
540      wincmd w
541      lhelpgrep quickfix
542      call assert_equal(1, winnr())
543      call assert_notequal([], getloclist(1))
544      call assert_equal([], getloclist(2))
545  endif
546
547  new | only
548
549  " Search for non existing help string
550  call assert_fails('Xhelpgrep a1b2c3', 'E480:')
551endfunc
552
553func Test_helpgrep()
554  call s:test_xhelpgrep('c')
555  helpclose
556  call s:test_xhelpgrep('l')
557endfunc
558
559func Test_errortitle()
560  augroup QfBufWinEnter
561    au!
562    au BufWinEnter * :let g:a=get(w:, 'quickfix_title', 'NONE')
563  augroup END
564  copen
565  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'')'}]
566  call setqflist(a)
567  call assert_equal(':setqflist()', g:a)
568  augroup QfBufWinEnter
569    au!
570  augroup END
571  augroup! QfBufWinEnter
572endfunc
573
574func Test_vimgreptitle()
575  augroup QfBufWinEnter
576    au!
577    au BufWinEnter * :let g:a=get(w:, 'quickfix_title', 'NONE')
578  augroup END
579  try
580    vimgrep /pattern/j file
581  catch /E480/
582  endtry
583  copen
584  call assert_equal(':    vimgrep /pattern/j file', g:a)
585  augroup QfBufWinEnter
586    au!
587  augroup END
588  augroup! QfBufWinEnter
589endfunc
590
591func XqfTitleTests(cchar)
592  call s:setup_commands(a:cchar)
593
594  Xgetexpr ['file:1:1:message']
595  let l = g:Xgetlist()
596  if a:cchar == 'c'
597    call setqflist(l, 'r')
598  else
599    call setloclist(0, l, 'r')
600  endif
601
602  Xopen
603  if a:cchar == 'c'
604    let title = ':setqflist()'
605  else
606    let title = ':setloclist()'
607  endif
608  call assert_equal(title, w:quickfix_title)
609  Xclose
610endfunc
611
612" Tests for quickfix window's title
613func Test_qf_title()
614  call XqfTitleTests('c')
615  call XqfTitleTests('l')
616endfunc
617
618" Tests for 'errorformat'
619func Test_efm()
620  let save_efm = &efm
621  set efm=%EEEE%m,%WWWW%m,%+CCCC%.%#,%-GGGG%.%#
622  cgetexpr ['WWWW', 'EEEE', 'CCCC']
623  let l = strtrans(string(map(getqflist(), '[v:val.text, v:val.valid]')))
624  call assert_equal("[['W', 1], ['E^@CCCC', 1]]", l)
625  cgetexpr ['WWWW', 'GGGG', 'EEEE', 'CCCC']
626  let l = strtrans(string(map(getqflist(), '[v:val.text, v:val.valid]')))
627  call assert_equal("[['W', 1], ['E^@CCCC', 1]]", l)
628  cgetexpr ['WWWW', 'GGGG', 'ZZZZ', 'EEEE', 'CCCC', 'YYYY']
629  let l = strtrans(string(map(getqflist(), '[v:val.text, v:val.valid]')))
630  call assert_equal("[['W', 1], ['ZZZZ', 0], ['E^@CCCC', 1], ['YYYY', 0]]", l)
631  let &efm = save_efm
632endfunc
633
634" This will test for problems in quickfix:
635" A. incorrectly copying location lists which caused the location list to show
636"    a different name than the file that was actually being displayed.
637" B. not reusing the window for which the location list window is opened but
638"    instead creating new windows.
639" C. make sure that the location list window is not reused instead of the
640"    window it belongs to.
641"
642" Set up the test environment:
643func ReadTestProtocol(name)
644  let base = substitute(a:name, '\v^test://(.*)%(\.[^.]+)?', '\1', '')
645  let word = substitute(base, '\v(.*)\..*', '\1', '')
646
647  setl modifiable
648  setl noreadonly
649  setl noswapfile
650  setl bufhidden=delete
651  %del _
652  " For problem 2:
653  " 'buftype' has to be set to reproduce the constant opening of new windows
654  setl buftype=nofile
655
656  call setline(1, word)
657
658  setl nomodified
659  setl nomodifiable
660  setl readonly
661  exe 'doautocmd BufRead ' . substitute(a:name, '\v^test://(.*)', '\1', '')
662endfunc
663
664func Test_locationlist()
665    enew
666
667    augroup testgroup
668      au!
669      autocmd BufReadCmd test://* call ReadTestProtocol(expand("<amatch>"))
670    augroup END
671
672    let words = [ "foo", "bar", "baz", "quux", "shmoo", "spam", "eggs" ]
673
674    let qflist = []
675    for word in words
676      call add(qflist, {'filename': 'test://' . word . '.txt', 'text': 'file ' . word . '.txt', })
677      " NOTE: problem 1:
678      " intentionally not setting 'lnum' so that the quickfix entries are not
679      " valid
680      call setloclist(0, qflist, ' ')
681    endfor
682
683    " Test A
684    lrewind
685    enew
686    lopen
687    4lnext
688    vert split
689    wincmd L
690    lopen
691    wincmd p
692    lnext
693    let fileName = expand("%")
694    wincmd p
695    let locationListFileName = substitute(getline(line('.')), '\([^|]*\)|.*', '\1', '')
696    let fileName = substitute(fileName, '\\', '/', 'g')
697    let locationListFileName = substitute(locationListFileName, '\\', '/', 'g')
698    call assert_equal("test://bar.txt", fileName)
699    call assert_equal("test://bar.txt", locationListFileName)
700
701    wincmd n | only
702
703    " Test B:
704    lrewind
705    lopen
706    2
707    exe "normal \<CR>"
708    wincmd p
709    3
710    exe "normal \<CR>"
711    wincmd p
712    4
713    exe "normal \<CR>"
714    call assert_equal(2, winnr('$'))
715    wincmd n | only
716
717    " Test C:
718    lrewind
719    lopen
720    " Let's move the location list window to the top to check whether it (the
721    " first window found) will be reused when we try to open new windows:
722    wincmd K
723    2
724    exe "normal \<CR>"
725    wincmd p
726    3
727    exe "normal \<CR>"
728    wincmd p
729    4
730    exe "normal \<CR>"
731    1wincmd w
732    call assert_equal('quickfix', &buftype)
733    2wincmd w
734    let bufferName = expand("%")
735    let bufferName = substitute(bufferName, '\\', '/', 'g')
736    call assert_equal('test://quux.txt', bufferName)
737
738    wincmd n | only
739
740    augroup! testgroup
741endfunc
742
743func Test_locationlist_curwin_was_closed()
744    augroup testgroup
745      au!
746      autocmd BufReadCmd test_curwin.txt call R(expand("<amatch>"))
747    augroup END
748
749    func! R(n)
750      quit
751    endfunc
752
753    new
754    let q = []
755    call add(q, {'filename': 'test_curwin.txt' })
756    call setloclist(0, q)
757    call assert_fails('lrewind', 'E924:')
758
759    augroup! testgroup
760endfunc
761
762func Test_locationlist_cross_tab_jump()
763  call writefile(['loclistfoo'], 'loclistfoo')
764  call writefile(['loclistbar'], 'loclistbar')
765  set switchbuf=usetab
766
767  edit loclistfoo
768  tabedit loclistbar
769  silent lgrep loclistfoo loclist*
770  call assert_equal(1, tabpagenr())
771
772  enew | only | tabonly
773  set switchbuf&vim
774  call delete('loclistfoo')
775  call delete('loclistbar')
776endfunc
777
778" More tests for 'errorformat'
779func Test_efm1()
780    if !has('unix')
781	" The 'errorformat' setting is different on non-Unix systems.
782	" This test works only on Unix-like systems.
783	return
784    endif
785
786    let l = [
787      \ '"Xtestfile", line 4.12: 1506-045 (S) Undeclared identifier fd_set.',
788      \ '"Xtestfile", line 6 col 19; this is an error',
789      \ 'gcc -c -DHAVE_CONFIsing-prototypes -I/usr/X11R6/include  version.c',
790      \ 'Xtestfile:9: parse error before `asd''',
791      \ 'make: *** [vim] Error 1',
792      \ 'in file "Xtestfile" linenr 10: there is an error',
793      \ '',
794      \ '2 returned',
795      \ '"Xtestfile", line 11 col 1; this is an error',
796      \ '"Xtestfile", line 12 col 2; this is another error',
797      \ '"Xtestfile", line 14:10; this is an error in column 10',
798      \ '=Xtestfile=, line 15:10; this is another error, but in vcol 10 this time',
799      \ '"Xtestfile", linenr 16: yet another problem',
800      \ 'Error in "Xtestfile" at line 17:',
801      \ 'x should be a dot',
802      \ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 17',
803      \ '            ^',
804      \ 'Error in "Xtestfile" at line 18:',
805      \ 'x should be a dot',
806      \ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 18',
807      \ '.............^',
808      \ 'Error in "Xtestfile" at line 19:',
809      \ 'x should be a dot',
810      \ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 19',
811      \ '--------------^',
812      \ 'Error in "Xtestfile" at line 20:',
813      \ 'x should be a dot',
814      \ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 20',
815      \ '	       ^',
816      \ '',
817      \ 'Does anyone know what is the problem and how to correction it?',
818      \ '"Xtestfile", line 21 col 9: What is the title of the quickfix window?',
819      \ '"Xtestfile", line 22 col 9: What is the title of the quickfix window?'
820      \ ]
821
822    call writefile(l, 'Xerrorfile1')
823    call writefile(l[:-2], 'Xerrorfile2')
824
825    let m = [
826	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  2',
827	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  3',
828	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  4',
829	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  5',
830	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  6',
831	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  7',
832	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  8',
833	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  9',
834	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 10',
835	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 11',
836	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 12',
837	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 13',
838	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 14',
839	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 15',
840	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 16',
841	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 17',
842	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 18',
843	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 19',
844	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 20',
845	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 21',
846	\ '	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 22'
847	\ ]
848    call writefile(m, 'Xtestfile')
849
850    let save_efm = &efm
851    set efm+==%f=\\,\ line\ %l%*\\D%v%*[^\ ]\ %m
852    set efm^=%AError\ in\ \"%f\"\ at\ line\ %l:,%Z%p^,%C%m
853
854    exe 'cf Xerrorfile2'
855    clast
856    copen
857    call assert_equal(':cf Xerrorfile2', w:quickfix_title)
858    wincmd p
859
860    exe 'cf Xerrorfile1'
861    call assert_equal([4, 12], [line('.'), col('.')])
862    cn
863    call assert_equal([6, 19], [line('.'), col('.')])
864    cn
865    call assert_equal([9, 2], [line('.'), col('.')])
866    cn
867    call assert_equal([10, 2], [line('.'), col('.')])
868    cn
869    call assert_equal([11, 1], [line('.'), col('.')])
870    cn
871    call assert_equal([12, 2], [line('.'), col('.')])
872    cn
873    call assert_equal([14, 10], [line('.'), col('.')])
874    cn
875    call assert_equal([15, 3, 10], [line('.'), col('.'), virtcol('.')])
876    cn
877    call assert_equal([16, 2], [line('.'), col('.')])
878    cn
879    call assert_equal([17, 6], [line('.'), col('.')])
880    cn
881    call assert_equal([18, 7], [line('.'), col('.')])
882    cn
883    call assert_equal([19, 8], [line('.'), col('.')])
884    cn
885    call assert_equal([20, 9], [line('.'), col('.')])
886    clast
887    cprev
888    cprev
889    wincmd w
890    call assert_equal(':cf Xerrorfile1', w:quickfix_title)
891    wincmd p
892
893    let &efm = save_efm
894    call delete('Xerrorfile1')
895    call delete('Xerrorfile2')
896    call delete('Xtestfile')
897endfunc
898
899" Test for quickfix directory stack support
900func s:dir_stack_tests(cchar)
901  call s:setup_commands(a:cchar)
902
903  let save_efm=&efm
904  set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f'
905
906  let lines = ["Entering dir 'dir1/a'",
907		\ 'habits2.txt:1:Nine Healthy Habits',
908		\ "Entering dir 'b'",
909		\ 'habits3.txt:2:0 Hours of television',
910		\ 'habits2.txt:7:5 Small meals',
911		\ "Entering dir 'dir1/c'",
912		\ 'habits4.txt:3:1 Hour of exercise',
913		\ "Leaving dir 'dir1/c'",
914		\ "Leaving dir 'dir1/a'",
915		\ 'habits1.txt:4:2 Liters of water',
916		\ "Entering dir 'dir2'",
917		\ 'habits5.txt:5:3 Cups of hot green tea',
918		\ "Leaving dir 'dir2'"
919		\]
920
921  Xexpr ""
922  for l in lines
923      Xaddexpr l
924  endfor
925
926  let qf = g:Xgetlist()
927
928  call assert_equal('dir1/a/habits2.txt', bufname(qf[1].bufnr))
929  call assert_equal(1, qf[1].lnum)
930  call assert_equal('dir1/a/b/habits3.txt', bufname(qf[3].bufnr))
931  call assert_equal(2, qf[3].lnum)
932  call assert_equal('dir1/a/habits2.txt', bufname(qf[4].bufnr))
933  call assert_equal(7, qf[4].lnum)
934  call assert_equal('dir1/c/habits4.txt', bufname(qf[6].bufnr))
935  call assert_equal(3, qf[6].lnum)
936  call assert_equal('habits1.txt', bufname(qf[9].bufnr))
937  call assert_equal(4, qf[9].lnum)
938  call assert_equal('dir2/habits5.txt', bufname(qf[11].bufnr))
939  call assert_equal(5, qf[11].lnum)
940
941  let &efm=save_efm
942endfunc
943
944" Tests for %D and %X errorformat options
945func Test_efm_dirstack()
946  " Create the directory stack and files
947  call mkdir('dir1')
948  call mkdir('dir1/a')
949  call mkdir('dir1/a/b')
950  call mkdir('dir1/c')
951  call mkdir('dir2')
952
953  let lines = ["Nine Healthy Habits",
954		\ "0 Hours of television",
955		\ "1 Hour of exercise",
956		\ "2 Liters of water",
957		\ "3 Cups of hot green tea",
958		\ "4 Short mental breaks",
959		\ "5 Small meals",
960		\ "6 AM wake up time",
961		\ "7 Minutes of laughter",
962		\ "8 Hours of sleep (at least)",
963		\ "9 PM end of the day and off to bed"
964		\ ]
965  call writefile(lines, 'habits1.txt')
966  call writefile(lines, 'dir1/a/habits2.txt')
967  call writefile(lines, 'dir1/a/b/habits3.txt')
968  call writefile(lines, 'dir1/c/habits4.txt')
969  call writefile(lines, 'dir2/habits5.txt')
970
971  call s:dir_stack_tests('c')
972  call s:dir_stack_tests('l')
973
974  call delete('dir1', 'rf')
975  call delete('dir2', 'rf')
976  call delete('habits1.txt')
977endfunc
978
979" Test for resync after continuing an ignored message
980func Xefm_ignore_continuations(cchar)
981  call s:setup_commands(a:cchar)
982
983  let save_efm = &efm
984
985  let &efm =
986	\ '%Eerror %m %l,' .
987	\ '%-Wignored %m %l,' .
988	\ '%+Cmore ignored %m %l,' .
989	\ '%Zignored end'
990  Xgetexpr ['ignored warning 1', 'more ignored continuation 2', 'ignored end', 'error resync 4']
991  let l = map(g:Xgetlist(), '[v:val.text, v:val.valid, v:val.lnum, v:val.type]')
992  call assert_equal([['resync', 1, 4, 'E']], l)
993
994  let &efm = save_efm
995endfunc
996
997func Test_efm_ignore_continuations()
998  call Xefm_ignore_continuations('c')
999  call Xefm_ignore_continuations('l')
1000endfunc
1001
1002" Tests for invalid error format specifies
1003func Xinvalid_efm_Tests(cchar)
1004  call s:setup_commands(a:cchar)
1005
1006  let save_efm = &efm
1007
1008  set efm=%f:%l:%m,%f:%f:%l:%m
1009  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E372:')
1010
1011  set efm=%f:%l:%m,%f:%l:%r:%m
1012  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E373:')
1013
1014  set efm=%f:%l:%m,%O:%f:%l:%m
1015  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E373:')
1016
1017  set efm=%f:%l:%m,%f:%l:%*[^a-z
1018  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E374:')
1019
1020  set efm=%f:%l:%m,%f:%l:%*c
1021  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E375:')
1022
1023  set efm=%f:%l:%m,%L%M%N
1024  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E376:')
1025
1026  set efm=%f:%l:%m,%f:%l:%m:%R
1027  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E377:')
1028
1029  set efm=
1030  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E378:')
1031
1032  set efm=%DEntering\ dir\ abc,%f:%l:%m
1033  call assert_fails('Xexpr ["Entering dir abc", "abc.txt:1:Hello world"]', 'E379:')
1034
1035  let &efm = save_efm
1036endfunc
1037
1038func Test_invalid_efm()
1039  call Xinvalid_efm_Tests('c')
1040  call Xinvalid_efm_Tests('l')
1041endfunc
1042
1043" TODO:
1044" Add tests for the following formats in 'errorformat'
1045"	%r  %O
1046func Test_efm2()
1047  let save_efm = &efm
1048
1049  " Test for %s format in efm
1050  set efm=%f:%s
1051  cexpr 'Xtestfile:Line search text'
1052  let l = getqflist()
1053  call assert_equal(l[0].pattern, '^\VLine search text\$')
1054  call assert_equal(l[0].lnum, 0)
1055
1056  let l = split(execute('clist', ''), "\n")
1057  call assert_equal([' 1 Xtestfile:^\VLine search text\$:  '], l)
1058
1059  " Test for %P, %Q and %t format specifiers
1060  let lines=["[Xtestfile1]",
1061	      \ "(1,17)  error: ';' missing",
1062	      \ "(21,2)  warning: variable 'z' not defined",
1063	      \ "(67,3)  error: end of file found before string ended",
1064	      \ "--",
1065	      \ "",
1066	      \ "[Xtestfile2]",
1067	      \ "--",
1068	      \ "",
1069	      \ "[Xtestfile3]",
1070	      \ "NEW compiler v1.1",
1071	      \ "(2,2)   warning: variable 'x' not defined",
1072	      \ "(67,3)  warning: 's' already defined",
1073	      \ "--"
1074	      \]
1075  set efm=%+P[%f]%r,(%l\\,%c)%*[\ ]%t%*[^:]:\ %m,%+Q--%r
1076  " To exercise the push/pop file functionality in quickfix, the test files
1077  " need to be created.
1078  call writefile(['Line1'], 'Xtestfile1')
1079  call writefile(['Line2'], 'Xtestfile2')
1080  call writefile(['Line3'], 'Xtestfile3')
1081  cexpr ""
1082  for l in lines
1083      caddexpr l
1084  endfor
1085  let l = getqflist()
1086  call assert_equal(12, len(l))
1087  call assert_equal(21, l[2].lnum)
1088  call assert_equal(2, l[2].col)
1089  call assert_equal('w', l[2].type)
1090  call assert_equal('e', l[3].type)
1091  call delete('Xtestfile1')
1092  call delete('Xtestfile2')
1093  call delete('Xtestfile3')
1094
1095  " Tests for %E, %C and %Z format specifiers
1096  let lines = ["Error 275",
1097	      \ "line 42",
1098	      \ "column 3",
1099	      \ "' ' expected after '--'"
1100	      \]
1101  set efm=%EError\ %n,%Cline\ %l,%Ccolumn\ %c,%Z%m
1102  cgetexpr lines
1103  let l = getqflist()
1104  call assert_equal(275, l[0].nr)
1105  call assert_equal(42, l[0].lnum)
1106  call assert_equal(3, l[0].col)
1107  call assert_equal('E', l[0].type)
1108  call assert_equal("\n' ' expected after '--'", l[0].text)
1109
1110  " Test for %>
1111  let lines = ["Error in line 147 of foo.c:",
1112	      \"unknown variable 'i'"
1113	      \]
1114  set efm=unknown\ variable\ %m,%E%>Error\ in\ line\ %l\ of\ %f:,%Z%m
1115  cgetexpr lines
1116  let l = getqflist()
1117  call assert_equal(147, l[0].lnum)
1118  call assert_equal('E', l[0].type)
1119  call assert_equal("\nunknown variable 'i'", l[0].text)
1120
1121  " Test for %A, %C and other formats
1122  let lines = [
1123	  \"==============================================================",
1124	  \"FAIL: testGetTypeIdCachesResult (dbfacadeTest.DjsDBFacadeTest)",
1125	  \"--------------------------------------------------------------",
1126	  \"Traceback (most recent call last):",
1127	  \'  File "unittests/dbfacadeTest.py", line 89, in testFoo',
1128	  \"    self.assertEquals(34, dtid)",
1129	  \'  File "/usr/lib/python2.2/unittest.py", line 286, in',
1130	  \" failUnlessEqual",
1131	  \"    raise self.failureException, \\",
1132	  \"AssertionError: 34 != 33",
1133	  \"",
1134	  \"--------------------------------------------------------------",
1135	  \"Ran 27 tests in 0.063s"
1136	  \]
1137  set efm=%C\ %.%#,%A\ \ File\ \"%f\"\\,\ line\ %l%.%#,%Z%[%^\ ]%\\@=%m
1138  cgetexpr lines
1139  let l = getqflist()
1140  call assert_equal(8, len(l))
1141  call assert_equal(89, l[4].lnum)
1142  call assert_equal(1, l[4].valid)
1143  call assert_equal('unittests/dbfacadeTest.py', bufname(l[4].bufnr))
1144
1145  " The following sequence of commands used to crash Vim
1146  set efm=%W%m
1147  cgetexpr ['msg1']
1148  let l = getqflist()
1149  call assert_equal(1, len(l), string(l))
1150  call assert_equal('msg1', l[0].text)
1151  set efm=%C%m
1152  lexpr 'msg2'
1153  let l = getloclist(0)
1154  call assert_equal(1, len(l), string(l))
1155  call assert_equal('msg2', l[0].text)
1156  lopen
1157  call setqflist([], 'r')
1158  caddbuf
1159  let l = getqflist()
1160  call assert_equal(1, len(l), string(l))
1161  call assert_equal('|| msg2', l[0].text)
1162
1163  new | only
1164  let &efm = save_efm
1165endfunc
1166
1167func XquickfixChangedByAutocmd(cchar)
1168  call s:setup_commands(a:cchar)
1169  if a:cchar == 'c'
1170    let ErrorNr = 'E925'
1171    func! ReadFunc()
1172      colder
1173      cgetexpr []
1174    endfunc
1175  else
1176    let ErrorNr = 'E926'
1177    func! ReadFunc()
1178      lolder
1179      lgetexpr []
1180    endfunc
1181  endif
1182
1183  augroup testgroup
1184    au!
1185    autocmd BufReadCmd test_changed.txt call ReadFunc()
1186  augroup END
1187
1188  new | only
1189  let words = [ "a", "b" ]
1190  let qflist = []
1191  for word in words
1192    call add(qflist, {'filename': 'test_changed.txt'})
1193    call g:Xsetlist(qflist, ' ')
1194  endfor
1195  call assert_fails('Xrewind', ErrorNr . ':')
1196
1197  augroup! testgroup
1198endfunc
1199
1200func Test_quickfix_was_changed_by_autocmd()
1201  call XquickfixChangedByAutocmd('c')
1202  call XquickfixChangedByAutocmd('l')
1203endfunc
1204
1205func Test_caddbuffer_to_empty()
1206  helpgr quickfix
1207  call setqflist([], 'r')
1208  cad
1209  try
1210    cn
1211  catch
1212    " number of matches is unknown
1213    call assert_true(v:exception =~ 'E553:')
1214  endtry
1215  quit!
1216endfunc
1217
1218func Test_cgetexpr_works()
1219  " this must not crash Vim
1220  cgetexpr [$x]
1221  lgetexpr [$x]
1222endfunc
1223
1224" Tests for the setqflist() and setloclist() functions
1225func SetXlistTests(cchar, bnum)
1226  call s:setup_commands(a:cchar)
1227
1228  call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 1},
1229	      \  {'bufnr': a:bnum, 'lnum': 2}])
1230  let l = g:Xgetlist()
1231  call assert_equal(2, len(l))
1232  call assert_equal(2, l[1].lnum)
1233
1234  Xnext
1235  call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 3}], 'a')
1236  let l = g:Xgetlist()
1237  call assert_equal(3, len(l))
1238  Xnext
1239  call assert_equal(3, line('.'))
1240
1241  " Appending entries to the list should not change the cursor position
1242  " in the quickfix window
1243  Xwindow
1244  1
1245  call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 4},
1246	      \  {'bufnr': a:bnum, 'lnum': 5}], 'a')
1247  call assert_equal(1, line('.'))
1248  close
1249
1250  call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 3},
1251	      \  {'bufnr': a:bnum, 'lnum': 4},
1252	      \  {'bufnr': a:bnum, 'lnum': 5}], 'r')
1253  let l = g:Xgetlist()
1254  call assert_equal(3, len(l))
1255  call assert_equal(5, l[2].lnum)
1256
1257  call g:Xsetlist([])
1258  let l = g:Xgetlist()
1259  call assert_equal(0, len(l))
1260
1261  " Tests for setting the 'valid' flag
1262  call g:Xsetlist([{'bufnr':a:bnum, 'lnum':4, 'valid':0}])
1263  Xwindow
1264  call assert_equal(1, winnr('$'))
1265  let l = g:Xgetlist()
1266  call g:Xsetlist(l)
1267  call assert_equal(0, g:Xgetlist()[0].valid)
1268  call g:Xsetlist([{'text':'Text1', 'valid':1}])
1269  Xwindow
1270  call assert_equal(2, winnr('$'))
1271  Xclose
1272  let save_efm = &efm
1273  set efm=%m
1274  Xgetexpr 'TestMessage'
1275  let l = g:Xgetlist()
1276  call g:Xsetlist(l)
1277  call assert_equal(1, g:Xgetlist()[0].valid)
1278  let &efm = save_efm
1279
1280  " Error cases:
1281  " Refer to a non-existing buffer and pass a non-dictionary type
1282  call assert_fails("call g:Xsetlist([{'bufnr':998, 'lnum':4}," .
1283	      \ " {'bufnr':999, 'lnum':5}])", 'E92:')
1284  call g:Xsetlist([[1, 2,3]])
1285  call assert_equal(0, len(g:Xgetlist()))
1286endfunc
1287
1288func Test_setqflist()
1289  new Xtestfile | only
1290  let bnum = bufnr('%')
1291  call setline(1, range(1,5))
1292
1293  call SetXlistTests('c', bnum)
1294  call SetXlistTests('l', bnum)
1295
1296  enew!
1297  call delete('Xtestfile')
1298endfunc
1299
1300func Xlist_empty_middle(cchar)
1301  call s:setup_commands(a:cchar)
1302
1303  " create three quickfix lists
1304  let @/ = 'Test_'
1305  Xvimgrep // test_quickfix.vim
1306  let testlen = len(g:Xgetlist())
1307  call assert_true(testlen > 0)
1308  Xvimgrep empty test_quickfix.vim
1309  call assert_true(len(g:Xgetlist()) > 0)
1310  Xvimgrep matches test_quickfix.vim
1311  let matchlen = len(g:Xgetlist())
1312  call assert_true(matchlen > 0)
1313  Xolder
1314  " make the middle list empty
1315  call g:Xsetlist([], 'r')
1316  call assert_true(len(g:Xgetlist()) == 0)
1317  Xolder
1318  call assert_equal(testlen, len(g:Xgetlist()))
1319  Xnewer
1320  Xnewer
1321  call assert_equal(matchlen, len(g:Xgetlist()))
1322endfunc
1323
1324func Test_setqflist_empty_middle()
1325  call Xlist_empty_middle('c')
1326  call Xlist_empty_middle('l')
1327endfunc
1328
1329func Xlist_empty_older(cchar)
1330  call s:setup_commands(a:cchar)
1331
1332  " create three quickfix lists
1333  Xvimgrep one test_quickfix.vim
1334  let onelen = len(g:Xgetlist())
1335  call assert_true(onelen > 0)
1336  Xvimgrep two test_quickfix.vim
1337  let twolen = len(g:Xgetlist())
1338  call assert_true(twolen > 0)
1339  Xvimgrep three test_quickfix.vim
1340  let threelen = len(g:Xgetlist())
1341  call assert_true(threelen > 0)
1342  Xolder 2
1343  " make the first list empty, check the others didn't change
1344  call g:Xsetlist([], 'r')
1345  call assert_true(len(g:Xgetlist()) == 0)
1346  Xnewer
1347  call assert_equal(twolen, len(g:Xgetlist()))
1348  Xnewer
1349  call assert_equal(threelen, len(g:Xgetlist()))
1350endfunc
1351
1352func Test_setqflist_empty_older()
1353  call Xlist_empty_older('c')
1354  call Xlist_empty_older('l')
1355endfunc
1356
1357func XquickfixSetListWithAct(cchar)
1358  call s:setup_commands(a:cchar)
1359
1360  let list1 = [{'filename': 'fnameA', 'text': 'A'},
1361          \    {'filename': 'fnameB', 'text': 'B'}]
1362  let list2 = [{'filename': 'fnameC', 'text': 'C'},
1363          \    {'filename': 'fnameD', 'text': 'D'},
1364          \    {'filename': 'fnameE', 'text': 'E'}]
1365
1366  " {action} is unspecified.  Same as specifing ' '.
1367  new | only
1368  silent! Xnewer 99
1369  call g:Xsetlist(list1)
1370  call g:Xsetlist(list2)
1371  let li = g:Xgetlist()
1372  call assert_equal(3, len(li))
1373  call assert_equal('C', li[0]['text'])
1374  call assert_equal('D', li[1]['text'])
1375  call assert_equal('E', li[2]['text'])
1376  silent! Xolder
1377  let li = g:Xgetlist()
1378  call assert_equal(2, len(li))
1379  call assert_equal('A', li[0]['text'])
1380  call assert_equal('B', li[1]['text'])
1381
1382  " {action} is specified ' '.
1383  new | only
1384  silent! Xnewer 99
1385  call g:Xsetlist(list1)
1386  call g:Xsetlist(list2, ' ')
1387  let li = g:Xgetlist()
1388  call assert_equal(3, len(li))
1389  call assert_equal('C', li[0]['text'])
1390  call assert_equal('D', li[1]['text'])
1391  call assert_equal('E', li[2]['text'])
1392  silent! Xolder
1393  let li = g:Xgetlist()
1394  call assert_equal(2, len(li))
1395  call assert_equal('A', li[0]['text'])
1396  call assert_equal('B', li[1]['text'])
1397
1398  " {action} is specified 'a'.
1399  new | only
1400  silent! Xnewer 99
1401  call g:Xsetlist(list1)
1402  call g:Xsetlist(list2, 'a')
1403  let li = g:Xgetlist()
1404  call assert_equal(5, len(li))
1405  call assert_equal('A', li[0]['text'])
1406  call assert_equal('B', li[1]['text'])
1407  call assert_equal('C', li[2]['text'])
1408  call assert_equal('D', li[3]['text'])
1409  call assert_equal('E', li[4]['text'])
1410
1411  " {action} is specified 'r'.
1412  new | only
1413  silent! Xnewer 99
1414  call g:Xsetlist(list1)
1415  call g:Xsetlist(list2, 'r')
1416  let li = g:Xgetlist()
1417  call assert_equal(3, len(li))
1418  call assert_equal('C', li[0]['text'])
1419  call assert_equal('D', li[1]['text'])
1420  call assert_equal('E', li[2]['text'])
1421
1422  " Test for wrong value.
1423  new | only
1424  call assert_fails("call g:Xsetlist(0)", 'E714:')
1425  call assert_fails("call g:Xsetlist(list1, '')", 'E927:')
1426  call assert_fails("call g:Xsetlist(list1, 'aa')", 'E927:')
1427  call assert_fails("call g:Xsetlist(list1, ' a')", 'E927:')
1428  call assert_fails("call g:Xsetlist(list1, 0)", 'E928:')
1429endfunc
1430
1431func Test_setqflist_invalid_nr()
1432  " The following command used to crash Vim
1433  call setqflist([], ' ', {'nr' : $XXX_DOES_NOT_EXIST})
1434endfunc
1435
1436func Test_quickfix_set_list_with_act()
1437  call XquickfixSetListWithAct('c')
1438  call XquickfixSetListWithAct('l')
1439endfunc
1440
1441func XLongLinesTests(cchar)
1442  let l = g:Xgetlist()
1443
1444  call assert_equal(4, len(l))
1445  call assert_equal(1, l[0].lnum)
1446  call assert_equal(1, l[0].col)
1447  call assert_equal(1975, len(l[0].text))
1448  call assert_equal(2, l[1].lnum)
1449  call assert_equal(1, l[1].col)
1450  call assert_equal(4070, len(l[1].text))
1451  call assert_equal(3, l[2].lnum)
1452  call assert_equal(1, l[2].col)
1453  call assert_equal(4070, len(l[2].text))
1454  call assert_equal(4, l[3].lnum)
1455  call assert_equal(1, l[3].col)
1456  call assert_equal(10, len(l[3].text))
1457
1458  call g:Xsetlist([], 'r')
1459endfunc
1460
1461func s:long_lines_tests(cchar)
1462  call s:setup_commands(a:cchar)
1463
1464  let testfile = 'samples/quickfix.txt'
1465
1466  " file
1467  exe 'Xgetfile' testfile
1468  call XLongLinesTests(a:cchar)
1469
1470  " list
1471  Xexpr readfile(testfile)
1472  call XLongLinesTests(a:cchar)
1473
1474  " string
1475  Xexpr join(readfile(testfile), "\n")
1476  call XLongLinesTests(a:cchar)
1477
1478  " buffer
1479  exe 'edit' testfile
1480  exe 'Xbuffer' bufnr('%')
1481  call XLongLinesTests(a:cchar)
1482endfunc
1483
1484func Test_long_lines()
1485  call s:long_lines_tests('c')
1486  call s:long_lines_tests('l')
1487endfunc
1488
1489func s:create_test_file(filename)
1490  let l = []
1491  for i in range(1, 20)
1492      call add(l, 'Line' . i)
1493  endfor
1494  call writefile(l, a:filename)
1495endfunc
1496
1497func Test_switchbuf()
1498  call s:create_test_file('Xqftestfile1')
1499  call s:create_test_file('Xqftestfile2')
1500  call s:create_test_file('Xqftestfile3')
1501
1502  new | only
1503  edit Xqftestfile1
1504  let file1_winid = win_getid()
1505  new Xqftestfile2
1506  let file2_winid = win_getid()
1507  cgetexpr ['Xqftestfile1:5:Line5',
1508		\ 'Xqftestfile1:6:Line6',
1509		\ 'Xqftestfile2:10:Line10',
1510		\ 'Xqftestfile2:11:Line11',
1511		\ 'Xqftestfile3:15:Line15',
1512		\ 'Xqftestfile3:16:Line16']
1513
1514  new
1515  let winid = win_getid()
1516  cfirst | cnext
1517  call assert_equal(winid, win_getid())
1518  2cnext
1519  call assert_equal(winid, win_getid())
1520  2cnext
1521  call assert_equal(winid, win_getid())
1522  enew
1523
1524  set switchbuf=useopen
1525  cfirst | cnext
1526  call assert_equal(file1_winid, win_getid())
1527  2cnext
1528  call assert_equal(file2_winid, win_getid())
1529  2cnext
1530  call assert_equal(file2_winid, win_getid())
1531
1532  enew | only
1533  set switchbuf=usetab
1534  tabedit Xqftestfile1
1535  tabedit Xqftestfile2
1536  tabedit Xqftestfile3
1537  tabfirst
1538  cfirst | cnext
1539  call assert_equal(2, tabpagenr())
1540  2cnext
1541  call assert_equal(3, tabpagenr())
1542  6cnext
1543  call assert_equal(4, tabpagenr())
1544  2cpfile
1545  call assert_equal(2, tabpagenr())
1546  2cnfile
1547  call assert_equal(4, tabpagenr())
1548  tabfirst | tabonly | enew
1549
1550  set switchbuf=split
1551  cfirst | cnext
1552  call assert_equal(1, winnr('$'))
1553  cnext | cnext
1554  call assert_equal(2, winnr('$'))
1555  cnext | cnext
1556  call assert_equal(3, winnr('$'))
1557  enew | only
1558
1559  set switchbuf=newtab
1560  cfirst | cnext
1561  call assert_equal(1, tabpagenr('$'))
1562  cnext | cnext
1563  call assert_equal(2, tabpagenr('$'))
1564  cnext | cnext
1565  call assert_equal(3, tabpagenr('$'))
1566  tabfirst | enew | tabonly | only
1567
1568  set switchbuf=
1569  edit Xqftestfile1
1570  let file1_winid = win_getid()
1571  new Xqftestfile2
1572  let file2_winid = win_getid()
1573  copen
1574  exe "normal 1G\<CR>"
1575  call assert_equal(file1_winid, win_getid())
1576  copen
1577  exe "normal 3G\<CR>"
1578  call assert_equal(file2_winid, win_getid())
1579  copen | only
1580  exe "normal 5G\<CR>"
1581  call assert_equal(2, winnr('$'))
1582  call assert_equal(1, bufwinnr('Xqftestfile3'))
1583
1584  " If only quickfix window is open in the current tabpage, jumping to an
1585  " entry with 'switchubf' set to 'usetab' should search in other tabpages.
1586  enew | only
1587  set switchbuf=usetab
1588  tabedit Xqftestfile1
1589  tabedit Xqftestfile2
1590  tabedit Xqftestfile3
1591  tabfirst
1592  copen | only
1593  clast
1594  call assert_equal(4, tabpagenr())
1595  tabfirst | tabonly | enew | only
1596
1597  call delete('Xqftestfile1')
1598  call delete('Xqftestfile2')
1599  call delete('Xqftestfile3')
1600  set switchbuf&vim
1601
1602  enew | only
1603endfunc
1604
1605func Xadjust_qflnum(cchar)
1606  call s:setup_commands(a:cchar)
1607
1608  enew | only
1609
1610  let fname = 'Xqftestfile' . a:cchar
1611  call s:create_test_file(fname)
1612  exe 'edit ' . fname
1613
1614  Xgetexpr [fname . ':5:Line5',
1615	      \ fname . ':10:Line10',
1616	      \ fname . ':15:Line15',
1617	      \ fname . ':20:Line20']
1618
1619  6,14delete
1620  call append(6, ['Buffer', 'Window'])
1621
1622  let l = g:Xgetlist()
1623
1624  call assert_equal(5, l[0].lnum)
1625  call assert_equal(6, l[2].lnum)
1626  call assert_equal(13, l[3].lnum)
1627
1628  enew!
1629  call delete(fname)
1630endfunc
1631
1632func Test_adjust_lnum()
1633  call setloclist(0, [])
1634  call Xadjust_qflnum('c')
1635  call setqflist([])
1636  call Xadjust_qflnum('l')
1637endfunc
1638
1639" Tests for the :grep/:lgrep and :grepadd/:lgrepadd commands
1640func s:test_xgrep(cchar)
1641  call s:setup_commands(a:cchar)
1642
1643  " The following lines are used for the grep test. Don't remove.
1644  " Grep_Test_Text: Match 1
1645  " Grep_Test_Text: Match 2
1646  " GrepAdd_Test_Text: Match 1
1647  " GrepAdd_Test_Text: Match 2
1648  enew! | only
1649  set makeef&vim
1650  silent Xgrep Grep_Test_Text: test_quickfix.vim
1651  call assert_true(len(g:Xgetlist()) == 3)
1652  Xopen
1653  call assert_true(w:quickfix_title =~ '^:grep')
1654  Xclose
1655  enew
1656  set makeef=Temp_File_##
1657  silent Xgrepadd GrepAdd_Test_Text: test_quickfix.vim
1658  call assert_true(len(g:Xgetlist()) == 6)
1659endfunc
1660
1661func Test_grep()
1662  if !has('unix')
1663    " The grepprg may not be set on non-Unix systems
1664    return
1665  endif
1666
1667  call s:test_xgrep('c')
1668  call s:test_xgrep('l')
1669endfunc
1670
1671func Test_two_windows()
1672  " Use one 'errorformat' for two windows.  Add an expression to each of them,
1673  " make sure they each keep their own state.
1674  set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f'
1675  call mkdir('Xone/a', 'p')
1676  call mkdir('Xtwo/a', 'p')
1677  let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7']
1678  call writefile(lines, 'Xone/a/one.txt')
1679  call writefile(lines, 'Xtwo/a/two.txt')
1680
1681  new one
1682  let one_id = win_getid()
1683  lexpr ""
1684  new two
1685  let two_id = win_getid()
1686  lexpr ""
1687
1688  laddexpr "Entering dir 'Xtwo/a'"
1689  call win_gotoid(one_id)
1690  laddexpr "Entering dir 'Xone/a'"
1691  call win_gotoid(two_id)
1692  laddexpr 'two.txt:5:two two two'
1693  call win_gotoid(one_id)
1694  laddexpr 'one.txt:3:one one one'
1695
1696  let loc_one = getloclist(one_id)
1697  call assert_equal('Xone/a/one.txt', bufname(loc_one[1].bufnr))
1698  call assert_equal(3, loc_one[1].lnum)
1699
1700  let loc_two = getloclist(two_id)
1701  call assert_equal('Xtwo/a/two.txt', bufname(loc_two[1].bufnr))
1702  call assert_equal(5, loc_two[1].lnum)
1703
1704  call win_gotoid(one_id)
1705  bwipe!
1706  call win_gotoid(two_id)
1707  bwipe!
1708  call delete('Xone', 'rf')
1709  call delete('Xtwo', 'rf')
1710endfunc
1711
1712func XbottomTests(cchar)
1713  call s:setup_commands(a:cchar)
1714
1715  " Calling lbottom without any errors should fail
1716  if a:cchar == 'l'
1717      call assert_fails('lbottom', 'E776:')
1718  endif
1719
1720  call g:Xsetlist([{'filename': 'foo', 'lnum': 42}])
1721  Xopen
1722  let wid = win_getid()
1723  call assert_equal(1, line('.'))
1724  wincmd w
1725  call g:Xsetlist([{'filename': 'var', 'lnum': 24}], 'a')
1726  Xbottom
1727  call win_gotoid(wid)
1728  call assert_equal(2, line('.'))
1729  Xclose
1730endfunc
1731
1732" Tests for the :cbottom and :lbottom commands
1733func Test_cbottom()
1734  call XbottomTests('c')
1735  call XbottomTests('l')
1736endfunc
1737
1738func HistoryTest(cchar)
1739  call s:setup_commands(a:cchar)
1740
1741  " clear all lists after the first one, then replace the first one.
1742  call g:Xsetlist([])
1743  call assert_fails('Xolder 99', 'E380:')
1744  let entry = {'filename': 'foo', 'lnum': 42}
1745  call g:Xsetlist([entry], 'r')
1746  call g:Xsetlist([entry, entry])
1747  call g:Xsetlist([entry, entry, entry])
1748  let res = split(execute(a:cchar . 'hist'), "\n")
1749  call assert_equal(3, len(res))
1750  let common = 'errors     :set' . (a:cchar == 'c' ? 'qf' : 'loc') . 'list()'
1751  call assert_equal('  error list 1 of 3; 1 ' . common, res[0])
1752  call assert_equal('  error list 2 of 3; 2 ' . common, res[1])
1753  call assert_equal('> error list 3 of 3; 3 ' . common, res[2])
1754
1755  call g:Xsetlist([], 'f')
1756  let l = split(execute(a:cchar . 'hist'), "\n")
1757  call assert_equal('No entries', l[0])
1758endfunc
1759
1760func Test_history()
1761  call HistoryTest('c')
1762  call HistoryTest('l')
1763endfunc
1764
1765func Test_duplicate_buf()
1766  " make sure we can get the highest buffer number
1767  edit DoesNotExist
1768  edit DoesNotExist2
1769  let last_buffer = bufnr("$")
1770
1771  " make sure only one buffer is created
1772  call writefile(['this one', 'that one'], 'Xgrepthis')
1773  vimgrep one Xgrepthis
1774  vimgrep one Xgrepthis
1775  call assert_equal(last_buffer + 1, bufnr("$"))
1776
1777  call delete('Xgrepthis')
1778endfunc
1779
1780" Quickfix/Location list set/get properties tests
1781func Xproperty_tests(cchar)
1782    call s:setup_commands(a:cchar)
1783
1784    " Error cases
1785    call assert_fails('call g:Xgetlist(99)', 'E715:')
1786    call assert_fails('call g:Xsetlist(99)', 'E714:')
1787    call assert_fails('call g:Xsetlist([], "a", [])', 'E715:')
1788
1789    " Set and get the title
1790    call g:Xsetlist([])
1791    Xopen
1792    wincmd p
1793    call g:Xsetlist([{'filename':'foo', 'lnum':27}])
1794    let s = g:Xsetlist([], 'a', {'title' : 'Sample'})
1795    call assert_equal(0, s)
1796    let d = g:Xgetlist({"title":1})
1797    call assert_equal('Sample', d.title)
1798    " Try setting title to a non-string value
1799    call assert_equal(-1, g:Xsetlist([], 'a', {'title' : ['Test']}))
1800    call assert_equal('Sample', g:Xgetlist({"title":1}).title)
1801
1802    Xopen
1803    call assert_equal('Sample', w:quickfix_title)
1804    Xclose
1805
1806    " Tests for action argument
1807    silent! Xolder 999
1808    let qfnr = g:Xgetlist({'all':1}).nr
1809    call g:Xsetlist([], 'r', {'title' : 'N1'})
1810    call assert_equal('N1', g:Xgetlist({'all':1}).title)
1811    call g:Xsetlist([], ' ', {'title' : 'N2'})
1812    call assert_equal(qfnr + 1, g:Xgetlist({'all':1}).nr)
1813
1814    let res = g:Xgetlist({'nr': 0})
1815    call assert_equal(qfnr + 1, res.nr)
1816    call assert_equal(['nr'], keys(res))
1817
1818    call g:Xsetlist([], ' ', {'title' : 'N3'})
1819    call assert_equal('N2', g:Xgetlist({'nr':2, 'title':1}).title)
1820
1821    " Changing the title of an earlier quickfix list
1822    call g:Xsetlist([], 'r', {'title' : 'NewTitle', 'nr' : 2})
1823    call assert_equal('NewTitle', g:Xgetlist({'nr':2, 'title':1}).title)
1824
1825    " Changing the title of an invalid quickfix list
1826    call assert_equal(-1, g:Xsetlist([], ' ',
1827		\ {'title' : 'SomeTitle', 'nr' : 99}))
1828    call assert_equal(-1, g:Xsetlist([], ' ',
1829		\ {'title' : 'SomeTitle', 'nr' : 'abc'}))
1830
1831    if a:cchar == 'c'
1832	copen
1833	call assert_equal({'winid':win_getid()}, getqflist({'winid':1}))
1834	cclose
1835    endif
1836
1837    " Invalid arguments
1838    call assert_fails('call g:Xgetlist([])', 'E715')
1839    call assert_fails('call g:Xsetlist([], "a", [])', 'E715')
1840    let s = g:Xsetlist([], 'a', {'abc':1})
1841    call assert_equal(-1, s)
1842
1843    call assert_equal({}, g:Xgetlist({'abc':1}))
1844    call assert_equal('', g:Xgetlist({'nr':99, 'title':1}).title)
1845    call assert_equal('', g:Xgetlist({'nr':[], 'title':1}).title)
1846
1847    if a:cchar == 'l'
1848	call assert_equal({}, getloclist(99, {'title': 1}))
1849    endif
1850
1851    " Context related tests
1852    let s = g:Xsetlist([], 'a', {'context':[1,2,3]})
1853    call assert_equal(0, s)
1854    call test_garbagecollect_now()
1855    let d = g:Xgetlist({'context':1})
1856    call assert_equal([1,2,3], d.context)
1857    call g:Xsetlist([], 'a', {'context':{'color':'green'}})
1858    let d = g:Xgetlist({'context':1})
1859    call assert_equal({'color':'green'}, d.context)
1860    call g:Xsetlist([], 'a', {'context':"Context info"})
1861    let d = g:Xgetlist({'context':1})
1862    call assert_equal("Context info", d.context)
1863    call g:Xsetlist([], 'a', {'context':246})
1864    let d = g:Xgetlist({'context':1})
1865    call assert_equal(246, d.context)
1866    if a:cchar == 'l'
1867	" Test for copying context across two different location lists
1868	new | only
1869	let w1_id = win_getid()
1870	let l = [1]
1871	call setloclist(0, [], 'a', {'context':l})
1872	new
1873	let w2_id = win_getid()
1874	call add(l, 2)
1875	call assert_equal([1, 2], getloclist(w1_id, {'context':1}).context)
1876	call assert_equal([1, 2], getloclist(w2_id, {'context':1}).context)
1877	unlet! l
1878	call assert_equal([1, 2], getloclist(w2_id, {'context':1}).context)
1879	only
1880	call setloclist(0, [], 'f')
1881	call assert_equal('', getloclist(0, {'context':1}).context)
1882    endif
1883
1884    " Test for changing the context of previous quickfix lists
1885    call g:Xsetlist([], 'f')
1886    Xexpr "One"
1887    Xexpr "Two"
1888    Xexpr "Three"
1889    call g:Xsetlist([], 'r', {'context' : [1], 'nr' : 1})
1890    call g:Xsetlist([], 'a', {'context' : [2], 'nr' : 2})
1891    " Also, check for setting the context using quickfix list number zero.
1892    call g:Xsetlist([], 'r', {'context' : [3], 'nr' : 0})
1893    call test_garbagecollect_now()
1894    let l = g:Xgetlist({'nr' : 1, 'context' : 1})
1895    call assert_equal([1], l.context)
1896    let l = g:Xgetlist({'nr' : 2, 'context' : 1})
1897    call assert_equal([2], l.context)
1898    let l = g:Xgetlist({'nr' : 3, 'context' : 1})
1899    call assert_equal([3], l.context)
1900
1901    " Test for changing the context through reference and for garbage
1902    " collection of quickfix context
1903    let l = ["red"]
1904    call g:Xsetlist([], ' ', {'context' : l})
1905    call add(l, "blue")
1906    let x = g:Xgetlist({'context' : 1})
1907    call add(x.context, "green")
1908    call assert_equal(["red", "blue", "green"], l)
1909    call assert_equal(["red", "blue", "green"], x.context)
1910    unlet l
1911    call test_garbagecollect_now()
1912    let m = g:Xgetlist({'context' : 1})
1913    call assert_equal(["red", "blue", "green"], m.context)
1914
1915    " Test for setting/getting items
1916    Xexpr ""
1917    let qfprev = g:Xgetlist({'nr':0})
1918    let s = g:Xsetlist([], ' ', {'title':'Green',
1919		\ 'items' : [{'filename':'F1', 'lnum':10}]})
1920    call assert_equal(0, s)
1921    let qfcur = g:Xgetlist({'nr':0})
1922    call assert_true(qfcur.nr == qfprev.nr + 1)
1923    let l = g:Xgetlist({'items':1})
1924    call assert_equal('F1', bufname(l.items[0].bufnr))
1925    call assert_equal(10, l.items[0].lnum)
1926    call g:Xsetlist([], 'a', {'items' : [{'filename':'F2', 'lnum':20},
1927		\  {'filename':'F2', 'lnum':30}]})
1928    let l = g:Xgetlist({'items':1})
1929    call assert_equal('F2', bufname(l.items[2].bufnr))
1930    call assert_equal(30, l.items[2].lnum)
1931    call g:Xsetlist([], 'r', {'items' : [{'filename':'F3', 'lnum':40}]})
1932    let l = g:Xgetlist({'items':1})
1933    call assert_equal('F3', bufname(l.items[0].bufnr))
1934    call assert_equal(40, l.items[0].lnum)
1935    call g:Xsetlist([], 'r', {'items' : []})
1936    let l = g:Xgetlist({'items':1})
1937    call assert_equal(0, len(l.items))
1938
1939    call g:Xsetlist([], 'r', {'title' : 'TestTitle'})
1940    call g:Xsetlist([], 'r', {'items' : [{'filename' : 'F1', 'lnum' : 10, 'text' : 'L10'}]})
1941    call g:Xsetlist([], 'r', {'items' : [{'filename' : 'F1', 'lnum' : 10, 'text' : 'L10'}]})
1942    call assert_equal('TestTitle', g:Xgetlist({'title' : 1}).title)
1943
1944    " The following used to crash Vim with address sanitizer
1945    call g:Xsetlist([], 'f')
1946    call g:Xsetlist([], 'a', {'items' : [{'filename':'F1', 'lnum':10}]})
1947    call assert_equal(10, g:Xgetlist({'items':1}).items[0].lnum)
1948
1949    " Try setting the items using a string
1950    call assert_equal(-1, g:Xsetlist([], ' ', {'items' : 'Test'}))
1951
1952    " Save and restore the quickfix stack
1953    call g:Xsetlist([], 'f')
1954    call assert_equal(0, g:Xgetlist({'nr':'$'}).nr)
1955    Xexpr "File1:10:Line1"
1956    Xexpr "File2:20:Line2"
1957    Xexpr "File3:30:Line3"
1958    let last_qf = g:Xgetlist({'nr':'$'}).nr
1959    call assert_equal(3, last_qf)
1960    let qstack = []
1961    for i in range(1, last_qf)
1962	let qstack = add(qstack, g:Xgetlist({'nr':i, 'all':1}))
1963    endfor
1964    call g:Xsetlist([], 'f')
1965    for i in range(len(qstack))
1966	call g:Xsetlist([], ' ', qstack[i])
1967    endfor
1968    call assert_equal(3, g:Xgetlist({'nr':'$'}).nr)
1969    call assert_equal(10, g:Xgetlist({'nr':1, 'items':1}).items[0].lnum)
1970    call assert_equal(20, g:Xgetlist({'nr':2, 'items':1}).items[0].lnum)
1971    call assert_equal(30, g:Xgetlist({'nr':3, 'items':1}).items[0].lnum)
1972    call g:Xsetlist([], 'f')
1973
1974    " Swap two quickfix lists
1975    Xexpr "File1:10:Line10"
1976    Xexpr "File2:20:Line20"
1977    Xexpr "File3:30:Line30"
1978    call g:Xsetlist([], 'r', {'nr':1,'title':'Colors','context':['Colors']})
1979    call g:Xsetlist([], 'r', {'nr':2,'title':'Fruits','context':['Fruits']})
1980    let l1=g:Xgetlist({'nr':1,'all':1})
1981    let l2=g:Xgetlist({'nr':2,'all':1})
1982    let save_id = l1.id
1983    let l1.id=l2.id
1984    let l2.id=save_id
1985    call g:Xsetlist([], 'r', l1)
1986    call g:Xsetlist([], 'r', l2)
1987    let newl1=g:Xgetlist({'nr':1,'all':1})
1988    let newl2=g:Xgetlist({'nr':2,'all':1})
1989    call assert_equal('Fruits', newl1.title)
1990    call assert_equal(['Fruits'], newl1.context)
1991    call assert_equal('Line20', newl1.items[0].text)
1992    call assert_equal('Colors', newl2.title)
1993    call assert_equal(['Colors'], newl2.context)
1994    call assert_equal('Line10', newl2.items[0].text)
1995    call g:Xsetlist([], 'f')
1996endfunc
1997
1998func Test_qf_property()
1999    call Xproperty_tests('c')
2000    call Xproperty_tests('l')
2001endfunc
2002
2003" Tests for the QuickFixCmdPre/QuickFixCmdPost autocommands
2004func QfAutoCmdHandler(loc, cmd)
2005  call add(g:acmds, a:loc . a:cmd)
2006endfunc
2007
2008func Test_Autocmd()
2009  autocmd QuickFixCmdPre * call QfAutoCmdHandler('pre', expand('<amatch>'))
2010  autocmd QuickFixCmdPost * call QfAutoCmdHandler('post', expand('<amatch>'))
2011
2012  let g:acmds = []
2013  cexpr "F1:10:Line 10"
2014  caddexpr "F1:20:Line 20"
2015  cgetexpr "F1:30:Line 30"
2016  cexpr ""
2017  caddexpr ""
2018  cgetexpr ""
2019  silent! cexpr non_existing_func()
2020  silent! caddexpr non_existing_func()
2021  silent! cgetexpr non_existing_func()
2022  let l = ['precexpr',
2023	      \ 'postcexpr',
2024	      \ 'precaddexpr',
2025	      \ 'postcaddexpr',
2026	      \ 'precgetexpr',
2027	      \ 'postcgetexpr',
2028	      \ 'precexpr',
2029	      \ 'postcexpr',
2030	      \ 'precaddexpr',
2031	      \ 'postcaddexpr',
2032	      \ 'precgetexpr',
2033	      \ 'postcgetexpr',
2034	      \ 'precexpr',
2035	      \ 'precaddexpr',
2036	      \ 'precgetexpr']
2037  call assert_equal(l, g:acmds)
2038
2039  let g:acmds = []
2040  enew! | call append(0, "F2:10:Line 10")
2041  cbuffer!
2042  enew! | call append(0, "F2:20:Line 20")
2043  cgetbuffer
2044  enew! | call append(0, "F2:30:Line 30")
2045  caddbuffer
2046  new
2047  let bnum = bufnr('%')
2048  bunload
2049  exe 'silent! cbuffer! ' . bnum
2050  exe 'silent! cgetbuffer ' . bnum
2051  exe 'silent! caddbuffer ' . bnum
2052  enew!
2053  let l = ['precbuffer',
2054	      \ 'postcbuffer',
2055	      \ 'precgetbuffer',
2056	      \ 'postcgetbuffer',
2057	      \ 'precaddbuffer',
2058	      \ 'postcaddbuffer',
2059	      \ 'precbuffer',
2060	      \ 'precgetbuffer',
2061	      \ 'precaddbuffer']
2062  call assert_equal(l, g:acmds)
2063
2064  call writefile(['Xtest:1:Line1'], 'Xtest')
2065  call writefile([], 'Xempty')
2066  let g:acmds = []
2067  cfile Xtest
2068  caddfile Xtest
2069  cgetfile Xtest
2070  cfile Xempty
2071  caddfile Xempty
2072  cgetfile Xempty
2073  silent! cfile do_not_exist
2074  silent! caddfile do_not_exist
2075  silent! cgetfile do_not_exist
2076  let l = ['precfile',
2077	      \ 'postcfile',
2078	      \ 'precaddfile',
2079	      \ 'postcaddfile',
2080	      \ 'precgetfile',
2081	      \ 'postcgetfile',
2082	      \ 'precfile',
2083	      \ 'postcfile',
2084	      \ 'precaddfile',
2085	      \ 'postcaddfile',
2086	      \ 'precgetfile',
2087	      \ 'postcgetfile',
2088	      \ 'precfile',
2089	      \ 'postcfile',
2090	      \ 'precaddfile',
2091	      \ 'postcaddfile',
2092	      \ 'precgetfile',
2093	      \ 'postcgetfile']
2094  call assert_equal(l, g:acmds)
2095
2096  let g:acmds = []
2097  helpgrep quickfix
2098  silent! helpgrep non_existing_help_topic
2099  vimgrep test Xtest
2100  vimgrepadd test Xtest
2101  silent! vimgrep non_existing_test Xtest
2102  silent! vimgrepadd non_existing_test Xtest
2103  set makeprg=
2104  silent! make
2105  set makeprg&
2106  let l = ['prehelpgrep',
2107	      \ 'posthelpgrep',
2108	      \ 'prehelpgrep',
2109	      \ 'posthelpgrep',
2110	      \ 'previmgrep',
2111	      \ 'postvimgrep',
2112	      \ 'previmgrepadd',
2113	      \ 'postvimgrepadd',
2114	      \ 'previmgrep',
2115	      \ 'postvimgrep',
2116	      \ 'previmgrepadd',
2117	      \ 'postvimgrepadd',
2118	      \ 'premake',
2119	      \ 'postmake']
2120  call assert_equal(l, g:acmds)
2121
2122  if has('unix')
2123    " Run this test only on Unix-like systems. The grepprg may not be set on
2124    " non-Unix systems.
2125    " The following lines are used for the grep test. Don't remove.
2126    " Grep_Autocmd_Text: Match 1
2127    " GrepAdd_Autocmd_Text: Match 2
2128    let g:acmds = []
2129    silent grep Grep_Autocmd_Text test_quickfix.vim
2130    silent grepadd GrepAdd_Autocmd_Text test_quickfix.vim
2131    silent grep abc123def Xtest
2132    silent grepadd abc123def Xtest
2133    let l = ['pregrep',
2134		\ 'postgrep',
2135		\ 'pregrepadd',
2136		\ 'postgrepadd',
2137		\ 'pregrep',
2138		\ 'postgrep',
2139		\ 'pregrepadd',
2140		\ 'postgrepadd']
2141    call assert_equal(l, g:acmds)
2142  endif
2143
2144  call delete('Xtest')
2145  call delete('Xempty')
2146  au! QuickFixCmdPre
2147  au! QuickFixCmdPost
2148endfunc
2149
2150func Test_Autocmd_Exception()
2151  set efm=%m
2152  lgetexpr '?'
2153
2154  try
2155    call DoesNotExit()
2156  catch
2157    lgetexpr '1'
2158  finally
2159    lgetexpr '1'
2160  endtry
2161
2162  call assert_equal('1', getloclist(0)[0].text)
2163
2164  set efm&vim
2165endfunc
2166
2167func Test_caddbuffer_wrong()
2168  " This used to cause a memory access in freed memory.
2169  let save_efm = &efm
2170  set efm=%EEEE%m,%WWWW,%+CCCC%>%#,%GGGG%.#
2171  cgetexpr ['WWWW', 'EEEE', 'CCCC']
2172  let &efm = save_efm
2173  caddbuffer
2174  bwipe!
2175endfunc
2176
2177func Test_caddexpr_wrong()
2178  " This used to cause a memory access in freed memory.
2179  cbuffer
2180  cbuffer
2181  copen
2182  let save_efm = &efm
2183  set efm=%
2184  call assert_fails('caddexpr ""', 'E376:')
2185  let &efm = save_efm
2186endfunc
2187
2188func Test_dirstack_cleanup()
2189  " This used to cause a memory access in freed memory.
2190  let save_efm = &efm
2191  lexpr '0'
2192  lopen
2193  fun X(c)
2194    let save_efm=&efm
2195    set efm=%D%f
2196    if a:c == 'c'
2197      caddexpr '::'
2198    else
2199      laddexpr ':0:0'
2200    endif
2201    let &efm=save_efm
2202  endfun
2203  call X('c')
2204  call X('l')
2205  call setqflist([], 'r')
2206  caddbuffer
2207  let &efm = save_efm
2208endfunc
2209
2210" Tests for jumping to entries from the location list window and quickfix
2211" window
2212func Test_cwindow_jump()
2213  set efm=%f%%%l%%%m
2214  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2215  lopen | only
2216  lfirst
2217  call assert_true(winnr('$') == 2)
2218  call assert_true(winnr() == 1)
2219  " Location list for the new window should be set
2220  call assert_true(getloclist(0)[2].text == 'Line 30')
2221
2222  " Open a scratch buffer
2223  " Open a new window and create a location list
2224  " Open the location list window and close the other window
2225  " Jump to an entry.
2226  " Should create a new window and jump to the entry. The scrtach buffer
2227  " should not be used.
2228  enew | only
2229  set buftype=nofile
2230  below new
2231  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2232  lopen
2233  2wincmd c
2234  lnext
2235  call assert_true(winnr('$') == 3)
2236  call assert_true(winnr() == 2)
2237
2238  " Open two windows with two different location lists
2239  " Open the location list window and close the previous window
2240  " Jump to an entry in the location list window
2241  " Should open the file in the first window and not set the location list.
2242  enew | only
2243  lgetexpr ["F1%5%Line 5"]
2244  below new
2245  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2246  lopen
2247  2wincmd c
2248  lnext
2249  call assert_true(winnr() == 1)
2250  call assert_true(getloclist(0)[0].text == 'Line 5')
2251
2252  enew | only
2253  cgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2254  copen
2255  cnext
2256  call assert_true(winnr('$') == 2)
2257  call assert_true(winnr() == 1)
2258
2259  enew | only
2260  set efm&vim
2261endfunc
2262
2263func XvimgrepTests(cchar)
2264  call s:setup_commands(a:cchar)
2265
2266  call writefile(['Editor:VIM vim',
2267	      \ 'Editor:Emacs EmAcS',
2268	      \ 'Editor:Notepad NOTEPAD'], 'Xtestfile1')
2269  call writefile(['Linux', 'MacOS', 'MS-Windows'], 'Xtestfile2')
2270
2271  " Error cases
2272  call assert_fails('Xvimgrep /abc *', 'E682:')
2273
2274  let @/=''
2275  call assert_fails('Xvimgrep // *', 'E35:')
2276
2277  call assert_fails('Xvimgrep abc', 'E683:')
2278  call assert_fails('Xvimgrep a1b2c3 Xtestfile1', 'E480:')
2279  call assert_fails('Xvimgrep pat Xa1b2c3', 'E480:')
2280
2281  Xexpr ""
2282  Xvimgrepadd Notepad Xtestfile1
2283  Xvimgrepadd MacOS Xtestfile2
2284  let l = g:Xgetlist()
2285  call assert_equal(2, len(l))
2286  call assert_equal('Editor:Notepad NOTEPAD', l[0].text)
2287
2288  Xvimgrep #\cvim#g Xtestfile?
2289  let l = g:Xgetlist()
2290  call assert_equal(2, len(l))
2291  call assert_equal(8, l[0].col)
2292  call assert_equal(12, l[1].col)
2293
2294  1Xvimgrep ?Editor? Xtestfile*
2295  let l = g:Xgetlist()
2296  call assert_equal(1, len(l))
2297  call assert_equal('Editor:VIM vim', l[0].text)
2298
2299  edit +3 Xtestfile2
2300  Xvimgrep +\cemacs+j Xtestfile1
2301  let l = g:Xgetlist()
2302  call assert_equal('Xtestfile2', bufname(''))
2303  call assert_equal('Editor:Emacs EmAcS', l[0].text)
2304
2305  " Test for unloading a buffer after vimgrep searched the buffer
2306  %bwipe
2307  Xvimgrep /Editor/j Xtestfile*
2308  call assert_equal(0, getbufinfo('Xtestfile1')[0].loaded)
2309  call assert_equal([], getbufinfo('Xtestfile2'))
2310
2311  call delete('Xtestfile1')
2312  call delete('Xtestfile2')
2313endfunc
2314
2315" Tests for the :vimgrep command
2316func Test_vimgrep()
2317  call XvimgrepTests('c')
2318  call XvimgrepTests('l')
2319endfunc
2320
2321func XfreeTests(cchar)
2322  call s:setup_commands(a:cchar)
2323
2324  enew | only
2325
2326  " Deleting the quickfix stack should work even When the current list is
2327  " somewhere in the middle of the stack
2328  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2329  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2330  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2331  Xolder
2332  call g:Xsetlist([], 'f')
2333  call assert_equal(0, len(g:Xgetlist()))
2334
2335  " After deleting the stack, adding a new list should create a stack with a
2336  " single list.
2337  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2338  call assert_equal(1, g:Xgetlist({'all':1}).nr)
2339
2340  " Deleting the stack from a quickfix window should update/clear the
2341  " quickfix/location list window.
2342  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2343  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2344  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2345  Xolder
2346  Xwindow
2347  call g:Xsetlist([], 'f')
2348  call assert_equal(2, winnr('$'))
2349  call assert_equal(1, line('$'))
2350  Xclose
2351
2352  " Deleting the stack from a non-quickfix window should update/clear the
2353  " quickfix/location list window.
2354  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2355  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2356  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2357  Xolder
2358  Xwindow
2359  wincmd p
2360  call g:Xsetlist([], 'f')
2361  call assert_equal(0, len(g:Xgetlist()))
2362  wincmd p
2363  call assert_equal(2, winnr('$'))
2364  call assert_equal(1, line('$'))
2365
2366  " After deleting the location list stack, if the location list window is
2367  " opened, then a new location list should be created. So opening the
2368  " location list window again should not create a new window.
2369  if a:cchar == 'l'
2370      lexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2371      wincmd p
2372      lopen
2373      call assert_equal(2, winnr('$'))
2374  endif
2375  Xclose
2376endfunc
2377
2378" Tests for the quickfix free functionality
2379func Test_qf_free()
2380  call XfreeTests('c')
2381  call XfreeTests('l')
2382endfunc
2383
2384" Test for buffer overflow when parsing lines and adding new entries to
2385" the quickfix list.
2386func Test_bufoverflow()
2387  set efm=%f:%l:%m
2388  cgetexpr ['File1:100:' . repeat('x', 1025)]
2389
2390  set efm=%+GCompiler:\ %.%#,%f:%l:%m
2391  cgetexpr ['Compiler: ' . repeat('a', 1015), 'File1:10:Hello World']
2392
2393  set efm=%DEntering\ directory\ %f,%f:%l:%m
2394  cgetexpr ['Entering directory ' . repeat('a', 1006),
2395	      \ 'File1:10:Hello World']
2396  set efm&vim
2397endfunc
2398
2399" Tests for getting the quickfix stack size
2400func XsizeTests(cchar)
2401  call s:setup_commands(a:cchar)
2402
2403  call g:Xsetlist([], 'f')
2404  call assert_equal(0, g:Xgetlist({'nr':'$'}).nr)
2405  call assert_equal('', g:Xgetlist({'nr':'$', 'all':1}).title)
2406  call assert_equal(0, g:Xgetlist({'nr':0}).nr)
2407
2408  Xexpr "File1:10:Line1"
2409  Xexpr "File2:20:Line2"
2410  Xexpr "File3:30:Line3"
2411  Xolder | Xolder
2412  call assert_equal(3, g:Xgetlist({'nr':'$'}).nr)
2413  call g:Xsetlist([], 'f')
2414
2415  Xexpr "File1:10:Line1"
2416  Xexpr "File2:20:Line2"
2417  Xexpr "File3:30:Line3"
2418  Xolder | Xolder
2419  call g:Xsetlist([], 'a', {'nr':'$', 'title':'Compiler'})
2420  call assert_equal('Compiler', g:Xgetlist({'nr':3, 'all':1}).title)
2421endfunc
2422
2423func Test_Qf_Size()
2424  call XsizeTests('c')
2425  call XsizeTests('l')
2426endfunc
2427
2428func Test_cclose_from_copen()
2429    augroup QF_Test
2430	au!
2431        au FileType qf :call assert_fails(':cclose', 'E788')
2432    augroup END
2433    copen
2434    augroup QF_Test
2435	au!
2436    augroup END
2437    augroup! QF_Test
2438endfunc
2439
2440func Test_cclose_in_autocmd()
2441  " Problem is only triggered if "starting" is zero, so that the OptionsSet
2442  " event will be triggered.
2443  call test_override('starting', 1)
2444  augroup QF_Test
2445    au!
2446    au FileType qf :call assert_fails(':cclose', 'E788')
2447  augroup END
2448  copen
2449  augroup QF_Test
2450    au!
2451  augroup END
2452  augroup! QF_Test
2453  call test_override('starting', 0)
2454endfunc
2455
2456func Test_resize_from_copen()
2457    augroup QF_Test
2458	au!
2459        au FileType qf resize 5
2460    augroup END
2461    try
2462	" This should succeed without any exception.  No other buffers are
2463	" involved in the autocmd.
2464	copen
2465    finally
2466	augroup QF_Test
2467	    au!
2468	augroup END
2469	augroup! QF_Test
2470    endtry
2471endfunc
2472
2473" Tests for the quickfix buffer b:changedtick variable
2474func Xchangedtick_tests(cchar)
2475  call s:setup_commands(a:cchar)
2476
2477  new | only
2478
2479  Xexpr "" | Xexpr "" | Xexpr ""
2480
2481  Xopen
2482  Xolder
2483  Xolder
2484  Xaddexpr "F1:10:Line10"
2485  Xaddexpr "F2:20:Line20"
2486  call g:Xsetlist([{"filename":"F3", "lnum":30, "text":"Line30"}], 'a')
2487  call g:Xsetlist([], 'f')
2488  call assert_equal(8, getbufvar('%', 'changedtick'))
2489  Xclose
2490endfunc
2491
2492func Test_changedtick()
2493  call Xchangedtick_tests('c')
2494  call Xchangedtick_tests('l')
2495endfunc
2496
2497" Tests for parsing an expression using setqflist()
2498func Xsetexpr_tests(cchar)
2499  call s:setup_commands(a:cchar)
2500
2501  let t = ["File1:10:Line10", "File1:20:Line20"]
2502  call g:Xsetlist([], ' ', {'lines' : t})
2503  call g:Xsetlist([], 'a', {'lines' : ["File1:30:Line30"]})
2504
2505  let l = g:Xgetlist()
2506  call assert_equal(3, len(l))
2507  call assert_equal(20, l[1].lnum)
2508  call assert_equal('Line30', l[2].text)
2509  call g:Xsetlist([], 'r', {'lines' : ["File2:5:Line5"]})
2510  let l = g:Xgetlist()
2511  call assert_equal(1, len(l))
2512  call assert_equal('Line5', l[0].text)
2513  call assert_equal(-1, g:Xsetlist([], 'a', {'lines' : 10}))
2514  call assert_equal(-1, g:Xsetlist([], 'a', {'lines' : "F1:10:L10"}))
2515
2516  call g:Xsetlist([], 'f')
2517  " Add entries to multiple lists
2518  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["File1:10:Line10"]})
2519  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["File2:20:Line20"]})
2520  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["File1:15:Line15"]})
2521  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["File2:25:Line25"]})
2522  call assert_equal('Line15', g:Xgetlist({'nr':1, 'items':1}).items[1].text)
2523  call assert_equal('Line25', g:Xgetlist({'nr':2, 'items':1}).items[1].text)
2524
2525  " Adding entries using a custom efm
2526  set efm&
2527  call g:Xsetlist([], ' ', {'efm' : '%f#%l#%m',
2528				\ 'lines' : ["F1#10#L10", "F2#20#L20"]})
2529  call assert_equal(20, g:Xgetlist({'items':1}).items[1].lnum)
2530  call g:Xsetlist([], 'a', {'efm' : '%f#%l#%m', 'lines' : ["F3:30:L30"]})
2531  call assert_equal('F3:30:L30', g:Xgetlist({'items':1}).items[2].text)
2532  call assert_equal(20, g:Xgetlist({'items':1}).items[1].lnum)
2533  call assert_equal(-1, g:Xsetlist([], 'a', {'efm' : [],
2534				\ 'lines' : ['F1:10:L10']}))
2535endfunc
2536
2537func Test_setexpr()
2538  call Xsetexpr_tests('c')
2539  call Xsetexpr_tests('l')
2540endfunc
2541
2542" Tests for per quickfix/location list directory stack
2543func Xmultidirstack_tests(cchar)
2544  call s:setup_commands(a:cchar)
2545
2546  call g:Xsetlist([], 'f')
2547  Xexpr "" | Xexpr ""
2548
2549  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["Entering dir 'Xone/a'"]})
2550  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["Entering dir 'Xtwo/a'"]})
2551  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["one.txt:3:one one one"]})
2552  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["two.txt:5:two two two"]})
2553
2554  let l1 = g:Xgetlist({'nr':1, 'items':1})
2555  let l2 = g:Xgetlist({'nr':2, 'items':1})
2556  call assert_equal('Xone/a/one.txt', bufname(l1.items[1].bufnr))
2557  call assert_equal(3, l1.items[1].lnum)
2558  call assert_equal('Xtwo/a/two.txt', bufname(l2.items[1].bufnr))
2559  call assert_equal(5, l2.items[1].lnum)
2560endfunc
2561
2562func Test_multidirstack()
2563  call mkdir('Xone/a', 'p')
2564  call mkdir('Xtwo/a', 'p')
2565  let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7']
2566  call writefile(lines, 'Xone/a/one.txt')
2567  call writefile(lines, 'Xtwo/a/two.txt')
2568  let save_efm = &efm
2569  set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f'
2570
2571  call Xmultidirstack_tests('c')
2572  call Xmultidirstack_tests('l')
2573
2574  let &efm = save_efm
2575  call delete('Xone', 'rf')
2576  call delete('Xtwo', 'rf')
2577endfunc
2578
2579" Tests for per quickfix/location list file stack
2580func Xmultifilestack_tests(cchar)
2581  call s:setup_commands(a:cchar)
2582
2583  call g:Xsetlist([], 'f')
2584  Xexpr "" | Xexpr ""
2585
2586  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["[one.txt]"]})
2587  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["[two.txt]"]})
2588  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["(3,5) one one one"]})
2589  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["(5,9) two two two"]})
2590
2591  let l1 = g:Xgetlist({'nr':1, 'items':1})
2592  let l2 = g:Xgetlist({'nr':2, 'items':1})
2593  call assert_equal('one.txt', bufname(l1.items[1].bufnr))
2594  call assert_equal(3, l1.items[1].lnum)
2595  call assert_equal('two.txt', bufname(l2.items[1].bufnr))
2596  call assert_equal(5, l2.items[1].lnum)
2597
2598  " Test for start of a new error line in the same line where a previous
2599  " error line ends with a file stack.
2600  let efm_val = 'Error\ l%l\ in\ %f,'
2601  let efm_val .= '%-P%>(%f%r,Error\ l%l\ in\ %m,%-Q)%r'
2602  let l = g:Xgetlist({'lines' : [
2603	      \ '(one.txt',
2604	      \ 'Error l4 in one.txt',
2605	      \ ') (two.txt',
2606	      \ 'Error l6 in two.txt',
2607	      \ ')',
2608	      \ 'Error l8 in one.txt'
2609	      \ ], 'efm' : efm_val})
2610  call assert_equal(3, len(l.items))
2611  call assert_equal('one.txt', bufname(l.items[0].bufnr))
2612  call assert_equal(4, l.items[0].lnum)
2613  call assert_equal('one.txt', l.items[0].text)
2614  call assert_equal('two.txt', bufname(l.items[1].bufnr))
2615  call assert_equal(6, l.items[1].lnum)
2616  call assert_equal('two.txt', l.items[1].text)
2617  call assert_equal('one.txt', bufname(l.items[2].bufnr))
2618  call assert_equal(8, l.items[2].lnum)
2619  call assert_equal('', l.items[2].text)
2620endfunc
2621
2622func Test_multifilestack()
2623  let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7']
2624  call writefile(lines, 'one.txt')
2625  call writefile(lines, 'two.txt')
2626  let save_efm = &efm
2627  set efm=%+P[%f],(%l\\,%c)\ %m,%-Q
2628
2629  call Xmultifilestack_tests('c')
2630  call Xmultifilestack_tests('l')
2631
2632  let &efm = save_efm
2633  call delete('one.txt')
2634  call delete('two.txt')
2635endfunc
2636
2637" Tests for per buffer 'efm' setting
2638func Test_perbuf_efm()
2639  call writefile(["File1-10-Line10"], 'one.txt')
2640  call writefile(["File2#20#Line20"], 'two.txt')
2641  set efm=%f#%l#%m
2642  new | only
2643  new
2644  setlocal efm=%f-%l-%m
2645  cfile one.txt
2646  wincmd w
2647  caddfile two.txt
2648
2649  let l = getqflist()
2650  call assert_equal(10, l[0].lnum)
2651  call assert_equal('Line20', l[1].text)
2652
2653  set efm&
2654  new | only
2655  call delete('one.txt')
2656  call delete('two.txt')
2657endfunc
2658
2659" Open multiple help windows using ":lhelpgrep
2660" This test used to crash Vim
2661func Test_Multi_LL_Help()
2662    new | only
2663    lhelpgrep window
2664    lopen
2665    e#
2666    lhelpgrep buffer
2667    call assert_equal(3, winnr('$'))
2668    call assert_true(len(getloclist(1)) != 0)
2669    call assert_true(len(getloclist(2)) != 0)
2670    new | only
2671endfunc
2672
2673" Tests for adding new quickfix lists using setqflist()
2674func XaddQf_tests(cchar)
2675  call s:setup_commands(a:cchar)
2676
2677  " Create a new list using ' ' for action
2678  call g:Xsetlist([], 'f')
2679  call g:Xsetlist([], ' ', {'title' : 'Test1'})
2680  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2681  call assert_equal(1, l.nr)
2682  call assert_equal('Test1', l.title)
2683
2684  " Create a new list using ' ' for action and '$' for 'nr'
2685  call g:Xsetlist([], 'f')
2686  call g:Xsetlist([], ' ', {'title' : 'Test2', 'nr' : '$'})
2687  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2688  call assert_equal(1, l.nr)
2689  call assert_equal('Test2', l.title)
2690
2691  " Create a new list using 'a' for action
2692  call g:Xsetlist([], 'f')
2693  call g:Xsetlist([], 'a', {'title' : 'Test3'})
2694  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2695  call assert_equal(1, l.nr)
2696  call assert_equal('Test3', l.title)
2697
2698  " Create a new list using 'a' for action and '$' for 'nr'
2699  call g:Xsetlist([], 'f')
2700  call g:Xsetlist([], 'a', {'title' : 'Test3', 'nr' : '$'})
2701  call g:Xsetlist([], 'a', {'title' : 'Test4'})
2702  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2703  call assert_equal(1, l.nr)
2704  call assert_equal('Test4', l.title)
2705
2706  " Adding a quickfix list should remove all the lists following the current
2707  " list.
2708  Xexpr "" | Xexpr "" | Xexpr ""
2709  silent! 10Xolder
2710  call g:Xsetlist([], ' ', {'title' : 'Test5'})
2711  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2712  call assert_equal(2, l.nr)
2713  call assert_equal('Test5', l.title)
2714
2715  " Add a quickfix list using '$' as the list number.
2716  let lastqf = g:Xgetlist({'nr':'$'}).nr
2717  silent! 99Xolder
2718  call g:Xsetlist([], ' ', {'nr' : '$', 'title' : 'Test6'})
2719  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2720  call assert_equal(lastqf + 1, l.nr)
2721  call assert_equal('Test6', l.title)
2722
2723  " Add a quickfix list using 'nr' set to one more than the quickfix
2724  " list size.
2725  let lastqf = g:Xgetlist({'nr':'$'}).nr
2726  silent! 99Xolder
2727  call g:Xsetlist([], ' ', {'nr' : lastqf + 1, 'title' : 'Test7'})
2728  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2729  call assert_equal(lastqf + 1, l.nr)
2730  call assert_equal('Test7', l.title)
2731
2732  " Add a quickfix list to a stack with 10 lists using 'nr' set to '$'
2733  exe repeat('Xexpr "" |', 9) . 'Xexpr ""'
2734  silent! 99Xolder
2735  call g:Xsetlist([], ' ', {'nr' : '$', 'title' : 'Test8'})
2736  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2737  call assert_equal(10, l.nr)
2738  call assert_equal('Test8', l.title)
2739
2740  " Add a quickfix list using 'nr' set to a value greater than 10
2741  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : 12, 'title' : 'Test9'}))
2742
2743  " Try adding a quickfix list with 'nr' set to a value greater than the
2744  " quickfix list size but less than 10.
2745  call g:Xsetlist([], 'f')
2746  Xexpr "" | Xexpr "" | Xexpr ""
2747  silent! 99Xolder
2748  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : 8, 'title' : 'Test10'}))
2749
2750  " Add a quickfix list using 'nr' set to a some string or list
2751  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : [1,2], 'title' : 'Test11'}))
2752endfunc
2753
2754func Test_add_qf()
2755  call XaddQf_tests('c')
2756  call XaddQf_tests('l')
2757endfunc
2758
2759" Test for getting the quickfix list items from some text without modifying
2760" the quickfix stack
2761func XgetListFromLines(cchar)
2762  call s:setup_commands(a:cchar)
2763  call g:Xsetlist([], 'f')
2764
2765  let l = g:Xgetlist({'lines' : ["File2:20:Line20", "File2:30:Line30"]}).items
2766  call assert_equal(2, len(l))
2767  call assert_equal(30, l[1].lnum)
2768
2769  call assert_equal({}, g:Xgetlist({'lines' : 10}))
2770  call assert_equal({}, g:Xgetlist({'lines' : 'File1:10:Line10'}))
2771  call assert_equal([], g:Xgetlist({'lines' : []}).items)
2772  call assert_equal([], g:Xgetlist({'lines' : [10, 20]}).items)
2773
2774  " Parse text using a custom efm
2775  set efm&
2776  let l = g:Xgetlist({'lines':['File3#30#Line30'], 'efm' : '%f#%l#%m'}).items
2777  call assert_equal('Line30', l[0].text)
2778  let l = g:Xgetlist({'lines':['File3:30:Line30'], 'efm' : '%f-%l-%m'}).items
2779  call assert_equal('File3:30:Line30', l[0].text)
2780  let l = g:Xgetlist({'lines':['File3:30:Line30'], 'efm' : [1,2]})
2781  call assert_equal({}, l)
2782  call assert_fails("call g:Xgetlist({'lines':['abc'], 'efm':'%2'})", 'E376:')
2783  call assert_fails("call g:Xgetlist({'lines':['abc'], 'efm':''})", 'E378:')
2784
2785  " Make sure that the quickfix stack is not modified
2786  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
2787endfunc
2788
2789func Test_get_list_from_lines()
2790  call XgetListFromLines('c')
2791  call XgetListFromLines('l')
2792endfunc
2793
2794" Tests for the quickfix list id
2795func Xqfid_tests(cchar)
2796  call s:setup_commands(a:cchar)
2797
2798  call g:Xsetlist([], 'f')
2799  call assert_equal(0, g:Xgetlist({'id':0}).id)
2800  Xexpr ''
2801  let start_id = g:Xgetlist({'id' : 0}).id
2802  Xexpr '' | Xexpr ''
2803  Xolder
2804  call assert_equal(start_id, g:Xgetlist({'id':0, 'nr':1}).id)
2805  call assert_equal(start_id + 1, g:Xgetlist({'id':0, 'nr':0}).id)
2806  call assert_equal(start_id + 2, g:Xgetlist({'id':0, 'nr':'$'}).id)
2807  call assert_equal(0, g:Xgetlist({'id':0, 'nr':99}).id)
2808  call assert_equal(2, g:Xgetlist({'id':start_id + 1, 'nr':0}).nr)
2809  call assert_equal(0, g:Xgetlist({'id':99, 'nr':0}).id)
2810  call assert_equal(0, g:Xgetlist({'id':"abc", 'nr':0}).id)
2811
2812  call g:Xsetlist([], 'a', {'id':start_id, 'context':[1,2]})
2813  call assert_equal([1,2], g:Xgetlist({'nr':1, 'context':1}).context)
2814  call g:Xsetlist([], 'a', {'id':start_id+1, 'lines':['F1:10:L10']})
2815  call assert_equal('L10', g:Xgetlist({'nr':2, 'items':1}).items[0].text)
2816  call assert_equal(-1, g:Xsetlist([], 'a', {'id':999, 'title':'Vim'}))
2817  call assert_equal(-1, g:Xsetlist([], 'a', {'id':'abc', 'title':'Vim'}))
2818
2819  let qfid = g:Xgetlist({'id':0, 'nr':0})
2820  call g:Xsetlist([], 'f')
2821  call assert_equal(0, g:Xgetlist({'id':qfid, 'nr':0}).id)
2822endfunc
2823
2824func Test_qf_id()
2825  call Xqfid_tests('c')
2826  call Xqfid_tests('l')
2827endfunc
2828
2829func Xqfjump_tests(cchar)
2830  call s:setup_commands(a:cchar)
2831
2832  call writefile(["Line1\tFoo", "Line2"], 'F1')
2833  call writefile(["Line1\tBar", "Line2"], 'F2')
2834  call writefile(["Line1\tBaz", "Line2"], 'F3')
2835
2836  call g:Xsetlist([], 'f')
2837
2838  " Tests for
2839  "   Jumping to a line using a pattern
2840  "   Jumping to a column greater than the last column in a line
2841  "   Jumping to a line greater than the last line in the file
2842  let l = []
2843  for i in range(1, 7)
2844    call add(l, {})
2845  endfor
2846  let l[0].filename='F1'
2847  let l[0].pattern='Line1'
2848  let l[1].filename='F2'
2849  let l[1].pattern='Line1'
2850  let l[2].filename='F3'
2851  let l[2].pattern='Line1'
2852  let l[3].filename='F3'
2853  let l[3].lnum=1
2854  let l[3].col=9
2855  let l[3].vcol=1
2856  let l[4].filename='F3'
2857  let l[4].lnum=99
2858  let l[5].filename='F3'
2859  let l[5].lnum=1
2860  let l[5].col=99
2861  let l[5].vcol=1
2862  let l[6].filename='F3'
2863  let l[6].pattern='abcxyz'
2864
2865  call g:Xsetlist([], ' ', {'items' : l})
2866  Xopen | only
2867  2Xnext
2868  call assert_equal(3, g:Xgetlist({'idx' : 0}).idx)
2869  call assert_equal('F3', bufname('%'))
2870  Xnext
2871  call assert_equal(7, col('.'))
2872  Xnext
2873  call assert_equal(2, line('.'))
2874  Xnext
2875  call assert_equal(9, col('.'))
2876  2
2877  Xnext
2878  call assert_equal(2, line('.'))
2879
2880  if a:cchar == 'l'
2881    " When jumping to a location list entry in the location list window and
2882    " no usable windows are available, then a new window should be opened.
2883    enew! | new | only
2884    call g:Xsetlist([], 'f')
2885    setlocal buftype=nofile
2886    new
2887    call g:Xsetlist([], ' ', {'lines' : ['F1:1:1:Line1', 'F1:2:2:Line2', 'F2:1:1:Line1', 'F2:2:2:Line2', 'F3:1:1:Line1', 'F3:2:2:Line2']})
2888    Xopen
2889    let winid = win_getid()
2890    wincmd p
2891    close
2892    call win_gotoid(winid)
2893    Xnext
2894    call assert_equal(3, winnr('$'))
2895    call assert_equal(1, winnr())
2896    call assert_equal(2, line('.'))
2897
2898    " When jumping to an entry in the location list window and the window
2899    " associated with the location list is not present and a window containing
2900    " the file is already present, then that window should be used.
2901    close
2902    belowright new
2903    call g:Xsetlist([], 'f')
2904    edit F3
2905    call win_gotoid(winid)
2906    Xlast
2907    call assert_equal(3, winnr())
2908    call assert_equal(6, g:Xgetlist({'size' : 1}).size)
2909    call assert_equal(winid, g:Xgetlist({'winid' : 1}).winid)
2910  endif
2911
2912  " Cleanup
2913  enew!
2914  new | only
2915
2916  call delete('F1')
2917  call delete('F2')
2918  call delete('F3')
2919endfunc
2920
2921func Test_qfjump()
2922  call Xqfjump_tests('c')
2923  call Xqfjump_tests('l')
2924endfunc
2925
2926" Tests for the getqflist() and getloclist() functions when the list is not
2927" present or is empty
2928func Xgetlist_empty_tests(cchar)
2929  call s:setup_commands(a:cchar)
2930
2931  " Empty quickfix stack
2932  call g:Xsetlist([], 'f')
2933  call assert_equal('', g:Xgetlist({'context' : 0}).context)
2934  call assert_equal(0, g:Xgetlist({'id' : 0}).id)
2935  call assert_equal(0, g:Xgetlist({'idx' : 0}).idx)
2936  call assert_equal([], g:Xgetlist({'items' : 0}).items)
2937  call assert_equal(0, g:Xgetlist({'nr' : 0}).nr)
2938  call assert_equal(0, g:Xgetlist({'size' : 0}).size)
2939  call assert_equal('', g:Xgetlist({'title' : 0}).title)
2940  call assert_equal(0, g:Xgetlist({'winid' : 0}).winid)
2941  call assert_equal(0, g:Xgetlist({'changedtick' : 0}).changedtick)
2942  call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [], 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0, 'changedtick': 0}, g:Xgetlist({'all' : 0}))
2943
2944  " Quickfix window with empty stack
2945  silent! Xopen
2946  let qfwinid = (a:cchar == 'c') ? win_getid() : 0
2947  call assert_equal(qfwinid, g:Xgetlist({'winid' : 0}).winid)
2948  Xclose
2949
2950  " Empty quickfix list
2951  Xexpr ""
2952  call assert_equal('', g:Xgetlist({'context' : 0}).context)
2953  call assert_notequal(0, g:Xgetlist({'id' : 0}).id)
2954  call assert_equal(0, g:Xgetlist({'idx' : 0}).idx)
2955  call assert_equal([], g:Xgetlist({'items' : 0}).items)
2956  call assert_notequal(0, g:Xgetlist({'nr' : 0}).nr)
2957  call assert_equal(0, g:Xgetlist({'size' : 0}).size)
2958  call assert_notequal('', g:Xgetlist({'title' : 0}).title)
2959  call assert_equal(0, g:Xgetlist({'winid' : 0}).winid)
2960  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
2961
2962  let qfid = g:Xgetlist({'id' : 0}).id
2963  call g:Xsetlist([], 'f')
2964
2965  " Non-existing quickfix identifier
2966  call assert_equal('', g:Xgetlist({'id' : qfid, 'context' : 0}).context)
2967  call assert_equal(0, g:Xgetlist({'id' : qfid}).id)
2968  call assert_equal(0, g:Xgetlist({'id' : qfid, 'idx' : 0}).idx)
2969  call assert_equal([], g:Xgetlist({'id' : qfid, 'items' : 0}).items)
2970  call assert_equal(0, g:Xgetlist({'id' : qfid, 'nr' : 0}).nr)
2971  call assert_equal(0, g:Xgetlist({'id' : qfid, 'size' : 0}).size)
2972  call assert_equal('', g:Xgetlist({'id' : qfid, 'title' : 0}).title)
2973  call assert_equal(0, g:Xgetlist({'id' : qfid, 'winid' : 0}).winid)
2974  call assert_equal(0, g:Xgetlist({'id' : qfid, 'changedtick' : 0}).changedtick)
2975  call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [], 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0, 'changedtick' : 0}, g:Xgetlist({'id' : qfid, 'all' : 0}))
2976
2977  " Non-existing quickfix list number
2978  call assert_equal('', g:Xgetlist({'nr' : 5, 'context' : 0}).context)
2979  call assert_equal(0, g:Xgetlist({'nr' : 5}).nr)
2980  call assert_equal(0, g:Xgetlist({'nr' : 5, 'idx' : 0}).idx)
2981  call assert_equal([], g:Xgetlist({'nr' : 5, 'items' : 0}).items)
2982  call assert_equal(0, g:Xgetlist({'nr' : 5, 'id' : 0}).id)
2983  call assert_equal(0, g:Xgetlist({'nr' : 5, 'size' : 0}).size)
2984  call assert_equal('', g:Xgetlist({'nr' : 5, 'title' : 0}).title)
2985  call assert_equal(0, g:Xgetlist({'nr' : 5, 'winid' : 0}).winid)
2986  call assert_equal(0, g:Xgetlist({'nr' : 5, 'changedtick' : 0}).changedtick)
2987  call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [], 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0, 'changedtick' : 0}, g:Xgetlist({'nr' : 5, 'all' : 0}))
2988endfunc
2989
2990func Test_getqflist()
2991  call Xgetlist_empty_tests('c')
2992  call Xgetlist_empty_tests('l')
2993endfunc
2994
2995func Test_getqflist_invalid_nr()
2996  " The following commands used to crash Vim
2997  cexpr ""
2998  call getqflist({'nr' : $XXX_DOES_NOT_EXIST_XXX})
2999
3000  " Cleanup
3001  call setqflist([], 'r')
3002endfunc
3003
3004" Tests for the quickfix/location list changedtick
3005func Xqftick_tests(cchar)
3006  call s:setup_commands(a:cchar)
3007
3008  call g:Xsetlist([], 'f')
3009
3010  Xexpr "F1:10:Line10"
3011  let qfid = g:Xgetlist({'id' : 0}).id
3012  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3013  Xaddexpr "F2:20:Line20\nF2:21:Line21"
3014  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
3015  call g:Xsetlist([], 'a', {'lines' : ["F3:30:Line30", "F3:31:Line31"]})
3016  call assert_equal(3, g:Xgetlist({'changedtick' : 0}).changedtick)
3017  call g:Xsetlist([], 'r', {'lines' : ["F4:40:Line40"]})
3018  call assert_equal(4, g:Xgetlist({'changedtick' : 0}).changedtick)
3019  call g:Xsetlist([], 'a', {'title' : 'New Title'})
3020  call assert_equal(5, g:Xgetlist({'changedtick' : 0}).changedtick)
3021
3022  enew!
3023  call append(0, ["F5:50:L50", "F6:60:L60"])
3024  Xaddbuffer
3025  call assert_equal(6, g:Xgetlist({'changedtick' : 0}).changedtick)
3026  enew!
3027
3028  call g:Xsetlist([], 'a', {'context' : {'bus' : 'pci'}})
3029  call assert_equal(7, g:Xgetlist({'changedtick' : 0}).changedtick)
3030  call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'},
3031	      \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], 'a')
3032  call assert_equal(8, g:Xgetlist({'changedtick' : 0}).changedtick)
3033  call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'},
3034	      \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], ' ')
3035  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3036  call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'},
3037	      \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], 'r')
3038  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
3039
3040  call writefile(["F8:80:L80", "F8:81:L81"], "Xone")
3041  Xfile Xone
3042  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3043  Xaddfile Xone
3044  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
3045
3046  " Test case for updating a non-current quickfix list
3047  call g:Xsetlist([], 'f')
3048  Xexpr "F1:1:L1"
3049  Xexpr "F2:2:L2"
3050  call g:Xsetlist([], 'a', {'nr' : 1, "lines" : ["F10:10:L10"]})
3051  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
3052  call assert_equal(2, g:Xgetlist({'nr' : 1, 'changedtick' : 0}).changedtick)
3053
3054  call delete("Xone")
3055endfunc
3056
3057func Test_qf_tick()
3058  call Xqftick_tests('c')
3059  call Xqftick_tests('l')
3060endfunc
3061
3062" The following test used to crash Vim.
3063" Open the location list window and close the regular window associated with
3064" the location list. When the garbage collection runs now, it incorrectly
3065" marks the location list context as not in use and frees the context.
3066func Test_ll_window_ctx()
3067  call setloclist(0, [], 'f')
3068  call setloclist(0, [], 'a', {'context' : []})
3069  lopen | only
3070  call test_garbagecollect_now()
3071  echo getloclist(0, {'context' : 1}).context
3072  enew | only
3073endfunc
3074
3075" The following test used to crash vim
3076func Test_lfile_crash()
3077  sp Xtest
3078  au QuickFixCmdPre * bw
3079  call assert_fails('lfile', 'E40')
3080  au! QuickFixCmdPre
3081endfunc
3082
3083" The following test used to crash vim
3084func Test_lbuffer_crash()
3085  sv Xtest
3086  augroup QF_Test
3087    au!
3088    au * * bw
3089  augroup END
3090  lbuffer
3091  augroup QF_Test
3092    au!
3093  augroup END
3094endfunc
3095
3096" The following test used to crash vim
3097func Test_lexpr_crash()
3098  augroup QF_Test
3099    au!
3100    au * * call setloclist(0, [], 'f')
3101  augroup END
3102  lexpr ""
3103  augroup QF_Test
3104    au!
3105  augroup END
3106  enew | only
3107endfunc
3108
3109" The following test used to crash Vim
3110func Test_lvimgrep_crash()
3111  sv Xtest
3112  augroup QF_Test
3113    au!
3114    au * * call setloclist(0, [], 'f')
3115  augroup END
3116  lvimgrep quickfix test_quickfix.vim
3117  augroup QF_Test
3118    au!
3119  augroup END
3120  enew | only
3121endfunc
3122
3123" Test for the position of the quickfix and location list window
3124func Test_qfwin_pos()
3125  " Open two windows
3126  new | only
3127  new
3128  cexpr ['F1:10:L10']
3129  copen
3130  " Quickfix window should be the bottom most window
3131  call assert_equal(3, winnr())
3132  close
3133  " Open at the very top
3134  wincmd t
3135  topleft copen
3136  call assert_equal(1, winnr())
3137  close
3138  " open left of the current window
3139  wincmd t
3140  below new
3141  leftabove copen
3142  call assert_equal(2, winnr())
3143  close
3144  " open right of the current window
3145  rightbelow copen
3146  call assert_equal(3, winnr())
3147  close
3148endfunc
3149
3150" Tests for quickfix/location lists changed by autocommands when
3151" :vimgrep/:lvimgrep commands are running.
3152func Test_vimgrep_autocmd()
3153  call setqflist([], 'f')
3154  call writefile(['stars'], 'Xtest1.txt')
3155  call writefile(['stars'], 'Xtest2.txt')
3156
3157  " Test 1:
3158  " When searching for a pattern using :vimgrep, if the quickfix list is
3159  " changed by an autocmd, the results should be added to the correct quickfix
3160  " list.
3161  autocmd BufRead Xtest2.txt cexpr '' | cexpr ''
3162  silent vimgrep stars Xtest*.txt
3163  call assert_equal(1, getqflist({'nr' : 0}).nr)
3164  call assert_equal(3, getqflist({'nr' : '$'}).nr)
3165  call assert_equal('Xtest2.txt', bufname(getqflist()[1].bufnr))
3166  au! BufRead Xtest2.txt
3167
3168  " Test 2:
3169  " When searching for a pattern using :vimgrep, if the quickfix list is
3170  " freed, then a error should be given.
3171  silent! %bwipe!
3172  call setqflist([], 'f')
3173  autocmd BufRead Xtest2.txt for i in range(10) | cexpr '' | endfor
3174  call assert_fails('vimgrep stars Xtest*.txt', 'E925:')
3175  au! BufRead Xtest2.txt
3176
3177  " Test 3:
3178  " When searching for a pattern using :lvimgrep, if the location list is
3179  " freed, then the command should error out.
3180  silent! %bwipe!
3181  let g:save_winid = win_getid()
3182  autocmd BufRead Xtest2.txt call setloclist(g:save_winid, [], 'f')
3183  call assert_fails('lvimgrep stars Xtest*.txt', 'E926:')
3184  au! BufRead Xtest2.txt
3185
3186  call delete('Xtest1.txt')
3187  call delete('Xtest2.txt')
3188  call setqflist([], 'f')
3189endfunc
3190
3191" The following test used to crash Vim
3192func Test_lhelpgrep_autocmd()
3193  lhelpgrep quickfix
3194  autocmd QuickFixCmdPost * call setloclist(0, [], 'f')
3195  lhelpgrep buffer
3196  call assert_equal('help', &filetype)
3197  call assert_equal(0, getloclist(0, {'nr' : '$'}).nr)
3198  lhelpgrep tabpage
3199  call assert_equal('help', &filetype)
3200  call assert_equal(1, getloclist(0, {'nr' : '$'}).nr)
3201  au! QuickFixCmdPost
3202  new | only
3203endfunc
3204