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_quickfix_set_list_with_act()
1432  call XquickfixSetListWithAct('c')
1433  call XquickfixSetListWithAct('l')
1434endfunc
1435
1436func XLongLinesTests(cchar)
1437  let l = g:Xgetlist()
1438
1439  call assert_equal(4, len(l))
1440  call assert_equal(1, l[0].lnum)
1441  call assert_equal(1, l[0].col)
1442  call assert_equal(1975, len(l[0].text))
1443  call assert_equal(2, l[1].lnum)
1444  call assert_equal(1, l[1].col)
1445  call assert_equal(4070, len(l[1].text))
1446  call assert_equal(3, l[2].lnum)
1447  call assert_equal(1, l[2].col)
1448  call assert_equal(4070, len(l[2].text))
1449  call assert_equal(4, l[3].lnum)
1450  call assert_equal(1, l[3].col)
1451  call assert_equal(10, len(l[3].text))
1452
1453  call g:Xsetlist([], 'r')
1454endfunc
1455
1456func s:long_lines_tests(cchar)
1457  call s:setup_commands(a:cchar)
1458
1459  let testfile = 'samples/quickfix.txt'
1460
1461  " file
1462  exe 'Xgetfile' testfile
1463  call XLongLinesTests(a:cchar)
1464
1465  " list
1466  Xexpr readfile(testfile)
1467  call XLongLinesTests(a:cchar)
1468
1469  " string
1470  Xexpr join(readfile(testfile), "\n")
1471  call XLongLinesTests(a:cchar)
1472
1473  " buffer
1474  exe 'edit' testfile
1475  exe 'Xbuffer' bufnr('%')
1476  call XLongLinesTests(a:cchar)
1477endfunc
1478
1479func Test_long_lines()
1480  call s:long_lines_tests('c')
1481  call s:long_lines_tests('l')
1482endfunc
1483
1484func s:create_test_file(filename)
1485  let l = []
1486  for i in range(1, 20)
1487      call add(l, 'Line' . i)
1488  endfor
1489  call writefile(l, a:filename)
1490endfunc
1491
1492func Test_switchbuf()
1493  call s:create_test_file('Xqftestfile1')
1494  call s:create_test_file('Xqftestfile2')
1495  call s:create_test_file('Xqftestfile3')
1496
1497  new | only
1498  edit Xqftestfile1
1499  let file1_winid = win_getid()
1500  new Xqftestfile2
1501  let file2_winid = win_getid()
1502  cgetexpr ['Xqftestfile1:5:Line5',
1503		\ 'Xqftestfile1:6:Line6',
1504		\ 'Xqftestfile2:10:Line10',
1505		\ 'Xqftestfile2:11:Line11',
1506		\ 'Xqftestfile3:15:Line15',
1507		\ 'Xqftestfile3:16:Line16']
1508
1509  new
1510  let winid = win_getid()
1511  cfirst | cnext
1512  call assert_equal(winid, win_getid())
1513  2cnext
1514  call assert_equal(winid, win_getid())
1515  2cnext
1516  call assert_equal(winid, win_getid())
1517  enew
1518
1519  set switchbuf=useopen
1520  cfirst | cnext
1521  call assert_equal(file1_winid, win_getid())
1522  2cnext
1523  call assert_equal(file2_winid, win_getid())
1524  2cnext
1525  call assert_equal(file2_winid, win_getid())
1526
1527  enew | only
1528  set switchbuf=usetab
1529  tabedit Xqftestfile1
1530  tabedit Xqftestfile2
1531  tabedit Xqftestfile3
1532  tabfirst
1533  cfirst | cnext
1534  call assert_equal(2, tabpagenr())
1535  2cnext
1536  call assert_equal(3, tabpagenr())
1537  6cnext
1538  call assert_equal(4, tabpagenr())
1539  2cpfile
1540  call assert_equal(2, tabpagenr())
1541  2cnfile
1542  call assert_equal(4, tabpagenr())
1543  tabfirst | tabonly | enew
1544
1545  set switchbuf=split
1546  cfirst | cnext
1547  call assert_equal(1, winnr('$'))
1548  cnext | cnext
1549  call assert_equal(2, winnr('$'))
1550  cnext | cnext
1551  call assert_equal(3, winnr('$'))
1552  enew | only
1553
1554  set switchbuf=newtab
1555  cfirst | cnext
1556  call assert_equal(1, tabpagenr('$'))
1557  cnext | cnext
1558  call assert_equal(2, tabpagenr('$'))
1559  cnext | cnext
1560  call assert_equal(3, tabpagenr('$'))
1561  tabfirst | enew | tabonly | only
1562
1563  set switchbuf=
1564  edit Xqftestfile1
1565  let file1_winid = win_getid()
1566  new Xqftestfile2
1567  let file2_winid = win_getid()
1568  copen
1569  exe "normal 1G\<CR>"
1570  call assert_equal(file1_winid, win_getid())
1571  copen
1572  exe "normal 3G\<CR>"
1573  call assert_equal(file2_winid, win_getid())
1574  copen | only
1575  exe "normal 5G\<CR>"
1576  call assert_equal(2, winnr('$'))
1577  call assert_equal(1, bufwinnr('Xqftestfile3'))
1578
1579  " If only quickfix window is open in the current tabpage, jumping to an
1580  " entry with 'switchubf' set to 'usetab' should search in other tabpages.
1581  enew | only
1582  set switchbuf=usetab
1583  tabedit Xqftestfile1
1584  tabedit Xqftestfile2
1585  tabedit Xqftestfile3
1586  tabfirst
1587  copen | only
1588  clast
1589  call assert_equal(4, tabpagenr())
1590  tabfirst | tabonly | enew | only
1591
1592  call delete('Xqftestfile1')
1593  call delete('Xqftestfile2')
1594  call delete('Xqftestfile3')
1595  set switchbuf&vim
1596
1597  enew | only
1598endfunc
1599
1600func Xadjust_qflnum(cchar)
1601  call s:setup_commands(a:cchar)
1602
1603  enew | only
1604
1605  let fname = 'Xqftestfile' . a:cchar
1606  call s:create_test_file(fname)
1607  exe 'edit ' . fname
1608
1609  Xgetexpr [fname . ':5:Line5',
1610	      \ fname . ':10:Line10',
1611	      \ fname . ':15:Line15',
1612	      \ fname . ':20:Line20']
1613
1614  6,14delete
1615  call append(6, ['Buffer', 'Window'])
1616
1617  let l = g:Xgetlist()
1618
1619  call assert_equal(5, l[0].lnum)
1620  call assert_equal(6, l[2].lnum)
1621  call assert_equal(13, l[3].lnum)
1622
1623  enew!
1624  call delete(fname)
1625endfunc
1626
1627func Test_adjust_lnum()
1628  call setloclist(0, [])
1629  call Xadjust_qflnum('c')
1630  call setqflist([])
1631  call Xadjust_qflnum('l')
1632endfunc
1633
1634" Tests for the :grep/:lgrep and :grepadd/:lgrepadd commands
1635func s:test_xgrep(cchar)
1636  call s:setup_commands(a:cchar)
1637
1638  " The following lines are used for the grep test. Don't remove.
1639  " Grep_Test_Text: Match 1
1640  " Grep_Test_Text: Match 2
1641  " GrepAdd_Test_Text: Match 1
1642  " GrepAdd_Test_Text: Match 2
1643  enew! | only
1644  set makeef&vim
1645  silent Xgrep Grep_Test_Text: test_quickfix.vim
1646  call assert_true(len(g:Xgetlist()) == 3)
1647  Xopen
1648  call assert_true(w:quickfix_title =~ '^:grep')
1649  Xclose
1650  enew
1651  set makeef=Temp_File_##
1652  silent Xgrepadd GrepAdd_Test_Text: test_quickfix.vim
1653  call assert_true(len(g:Xgetlist()) == 6)
1654endfunc
1655
1656func Test_grep()
1657  if !has('unix')
1658    " The grepprg may not be set on non-Unix systems
1659    return
1660  endif
1661
1662  call s:test_xgrep('c')
1663  call s:test_xgrep('l')
1664endfunc
1665
1666func Test_two_windows()
1667  " Use one 'errorformat' for two windows.  Add an expression to each of them,
1668  " make sure they each keep their own state.
1669  set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f'
1670  call mkdir('Xone/a', 'p')
1671  call mkdir('Xtwo/a', 'p')
1672  let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7']
1673  call writefile(lines, 'Xone/a/one.txt')
1674  call writefile(lines, 'Xtwo/a/two.txt')
1675
1676  new one
1677  let one_id = win_getid()
1678  lexpr ""
1679  new two
1680  let two_id = win_getid()
1681  lexpr ""
1682
1683  laddexpr "Entering dir 'Xtwo/a'"
1684  call win_gotoid(one_id)
1685  laddexpr "Entering dir 'Xone/a'"
1686  call win_gotoid(two_id)
1687  laddexpr 'two.txt:5:two two two'
1688  call win_gotoid(one_id)
1689  laddexpr 'one.txt:3:one one one'
1690
1691  let loc_one = getloclist(one_id)
1692  call assert_equal('Xone/a/one.txt', bufname(loc_one[1].bufnr))
1693  call assert_equal(3, loc_one[1].lnum)
1694
1695  let loc_two = getloclist(two_id)
1696  call assert_equal('Xtwo/a/two.txt', bufname(loc_two[1].bufnr))
1697  call assert_equal(5, loc_two[1].lnum)
1698
1699  call win_gotoid(one_id)
1700  bwipe!
1701  call win_gotoid(two_id)
1702  bwipe!
1703  call delete('Xone', 'rf')
1704  call delete('Xtwo', 'rf')
1705endfunc
1706
1707func XbottomTests(cchar)
1708  call s:setup_commands(a:cchar)
1709
1710  " Calling lbottom without any errors should fail
1711  if a:cchar == 'l'
1712      call assert_fails('lbottom', 'E776:')
1713  endif
1714
1715  call g:Xsetlist([{'filename': 'foo', 'lnum': 42}])
1716  Xopen
1717  let wid = win_getid()
1718  call assert_equal(1, line('.'))
1719  wincmd w
1720  call g:Xsetlist([{'filename': 'var', 'lnum': 24}], 'a')
1721  Xbottom
1722  call win_gotoid(wid)
1723  call assert_equal(2, line('.'))
1724  Xclose
1725endfunc
1726
1727" Tests for the :cbottom and :lbottom commands
1728func Test_cbottom()
1729  call XbottomTests('c')
1730  call XbottomTests('l')
1731endfunc
1732
1733func HistoryTest(cchar)
1734  call s:setup_commands(a:cchar)
1735
1736  " clear all lists after the first one, then replace the first one.
1737  call g:Xsetlist([])
1738  call assert_fails('Xolder 99', 'E380:')
1739  let entry = {'filename': 'foo', 'lnum': 42}
1740  call g:Xsetlist([entry], 'r')
1741  call g:Xsetlist([entry, entry])
1742  call g:Xsetlist([entry, entry, entry])
1743  let res = split(execute(a:cchar . 'hist'), "\n")
1744  call assert_equal(3, len(res))
1745  let common = 'errors     :set' . (a:cchar == 'c' ? 'qf' : 'loc') . 'list()'
1746  call assert_equal('  error list 1 of 3; 1 ' . common, res[0])
1747  call assert_equal('  error list 2 of 3; 2 ' . common, res[1])
1748  call assert_equal('> error list 3 of 3; 3 ' . common, res[2])
1749
1750  call g:Xsetlist([], 'f')
1751  let l = split(execute(a:cchar . 'hist'), "\n")
1752  call assert_equal('No entries', l[0])
1753endfunc
1754
1755func Test_history()
1756  call HistoryTest('c')
1757  call HistoryTest('l')
1758endfunc
1759
1760func Test_duplicate_buf()
1761  " make sure we can get the highest buffer number
1762  edit DoesNotExist
1763  edit DoesNotExist2
1764  let last_buffer = bufnr("$")
1765
1766  " make sure only one buffer is created
1767  call writefile(['this one', 'that one'], 'Xgrepthis')
1768  vimgrep one Xgrepthis
1769  vimgrep one Xgrepthis
1770  call assert_equal(last_buffer + 1, bufnr("$"))
1771
1772  call delete('Xgrepthis')
1773endfunc
1774
1775" Quickfix/Location list set/get properties tests
1776func Xproperty_tests(cchar)
1777    call s:setup_commands(a:cchar)
1778
1779    " Error cases
1780    call assert_fails('call g:Xgetlist(99)', 'E715:')
1781    call assert_fails('call g:Xsetlist(99)', 'E714:')
1782    call assert_fails('call g:Xsetlist([], "a", [])', 'E715:')
1783
1784    " Set and get the title
1785    call g:Xsetlist([])
1786    Xopen
1787    wincmd p
1788    call g:Xsetlist([{'filename':'foo', 'lnum':27}])
1789    let s = g:Xsetlist([], 'a', {'title' : 'Sample'})
1790    call assert_equal(0, s)
1791    let d = g:Xgetlist({"title":1})
1792    call assert_equal('Sample', d.title)
1793
1794    Xopen
1795    call assert_equal('Sample', w:quickfix_title)
1796    Xclose
1797
1798    " Tests for action argument
1799    silent! Xolder 999
1800    let qfnr = g:Xgetlist({'all':1}).nr
1801    call g:Xsetlist([], 'r', {'title' : 'N1'})
1802    call assert_equal('N1', g:Xgetlist({'all':1}).title)
1803    call g:Xsetlist([], ' ', {'title' : 'N2'})
1804    call assert_equal(qfnr + 1, g:Xgetlist({'all':1}).nr)
1805
1806    let res = g:Xgetlist({'nr': 0})
1807    call assert_equal(qfnr + 1, res.nr)
1808    call assert_equal(['nr'], keys(res))
1809
1810    call g:Xsetlist([], ' ', {'title' : 'N3'})
1811    call assert_equal('N2', g:Xgetlist({'nr':2, 'title':1}).title)
1812
1813    " Changing the title of an earlier quickfix list
1814    call g:Xsetlist([], 'r', {'title' : 'NewTitle', 'nr' : 2})
1815    call assert_equal('NewTitle', g:Xgetlist({'nr':2, 'title':1}).title)
1816
1817    " Changing the title of an invalid quickfix list
1818    call assert_equal(-1, g:Xsetlist([], ' ',
1819		\ {'title' : 'SomeTitle', 'nr' : 99}))
1820    call assert_equal(-1, g:Xsetlist([], ' ',
1821		\ {'title' : 'SomeTitle', 'nr' : 'abc'}))
1822
1823    if a:cchar == 'c'
1824	copen
1825	call assert_equal({'winid':win_getid()}, getqflist({'winid':1}))
1826	cclose
1827    endif
1828
1829    " Invalid arguments
1830    call assert_fails('call g:Xgetlist([])', 'E715')
1831    call assert_fails('call g:Xsetlist([], "a", [])', 'E715')
1832    let s = g:Xsetlist([], 'a', {'abc':1})
1833    call assert_equal(-1, s)
1834
1835    call assert_equal({}, g:Xgetlist({'abc':1}))
1836    call assert_equal('', g:Xgetlist({'nr':99, 'title':1}).title)
1837    call assert_equal('', g:Xgetlist({'nr':[], 'title':1}).title)
1838
1839    if a:cchar == 'l'
1840	call assert_equal({}, getloclist(99, {'title': 1}))
1841    endif
1842
1843    " Context related tests
1844    let s = g:Xsetlist([], 'a', {'context':[1,2,3]})
1845    call assert_equal(0, s)
1846    call test_garbagecollect_now()
1847    let d = g:Xgetlist({'context':1})
1848    call assert_equal([1,2,3], d.context)
1849    call g:Xsetlist([], 'a', {'context':{'color':'green'}})
1850    let d = g:Xgetlist({'context':1})
1851    call assert_equal({'color':'green'}, d.context)
1852    call g:Xsetlist([], 'a', {'context':"Context info"})
1853    let d = g:Xgetlist({'context':1})
1854    call assert_equal("Context info", d.context)
1855    call g:Xsetlist([], 'a', {'context':246})
1856    let d = g:Xgetlist({'context':1})
1857    call assert_equal(246, d.context)
1858    if a:cchar == 'l'
1859	" Test for copying context across two different location lists
1860	new | only
1861	let w1_id = win_getid()
1862	let l = [1]
1863	call setloclist(0, [], 'a', {'context':l})
1864	new
1865	let w2_id = win_getid()
1866	call add(l, 2)
1867	call assert_equal([1, 2], getloclist(w1_id, {'context':1}).context)
1868	call assert_equal([1, 2], getloclist(w2_id, {'context':1}).context)
1869	unlet! l
1870	call assert_equal([1, 2], getloclist(w2_id, {'context':1}).context)
1871	only
1872	call setloclist(0, [], 'f')
1873	call assert_equal('', getloclist(0, {'context':1}).context)
1874    endif
1875
1876    " Test for changing the context of previous quickfix lists
1877    call g:Xsetlist([], 'f')
1878    Xexpr "One"
1879    Xexpr "Two"
1880    Xexpr "Three"
1881    call g:Xsetlist([], 'r', {'context' : [1], 'nr' : 1})
1882    call g:Xsetlist([], 'a', {'context' : [2], 'nr' : 2})
1883    " Also, check for setting the context using quickfix list number zero.
1884    call g:Xsetlist([], 'r', {'context' : [3], 'nr' : 0})
1885    call test_garbagecollect_now()
1886    let l = g:Xgetlist({'nr' : 1, 'context' : 1})
1887    call assert_equal([1], l.context)
1888    let l = g:Xgetlist({'nr' : 2, 'context' : 1})
1889    call assert_equal([2], l.context)
1890    let l = g:Xgetlist({'nr' : 3, 'context' : 1})
1891    call assert_equal([3], l.context)
1892
1893    " Test for changing the context through reference and for garbage
1894    " collection of quickfix context
1895    let l = ["red"]
1896    call g:Xsetlist([], ' ', {'context' : l})
1897    call add(l, "blue")
1898    let x = g:Xgetlist({'context' : 1})
1899    call add(x.context, "green")
1900    call assert_equal(["red", "blue", "green"], l)
1901    call assert_equal(["red", "blue", "green"], x.context)
1902    unlet l
1903    call test_garbagecollect_now()
1904    let m = g:Xgetlist({'context' : 1})
1905    call assert_equal(["red", "blue", "green"], m.context)
1906
1907    " Test for setting/getting items
1908    Xexpr ""
1909    let qfprev = g:Xgetlist({'nr':0})
1910    let s = g:Xsetlist([], ' ', {'title':'Green',
1911		\ 'items' : [{'filename':'F1', 'lnum':10}]})
1912    call assert_equal(0, s)
1913    let qfcur = g:Xgetlist({'nr':0})
1914    call assert_true(qfcur.nr == qfprev.nr + 1)
1915    let l = g:Xgetlist({'items':1})
1916    call assert_equal('F1', bufname(l.items[0].bufnr))
1917    call assert_equal(10, l.items[0].lnum)
1918    call g:Xsetlist([], 'a', {'items' : [{'filename':'F2', 'lnum':20},
1919		\  {'filename':'F2', 'lnum':30}]})
1920    let l = g:Xgetlist({'items':1})
1921    call assert_equal('F2', bufname(l.items[2].bufnr))
1922    call assert_equal(30, l.items[2].lnum)
1923    call g:Xsetlist([], 'r', {'items' : [{'filename':'F3', 'lnum':40}]})
1924    let l = g:Xgetlist({'items':1})
1925    call assert_equal('F3', bufname(l.items[0].bufnr))
1926    call assert_equal(40, l.items[0].lnum)
1927    call g:Xsetlist([], 'r', {'items' : []})
1928    let l = g:Xgetlist({'items':1})
1929    call assert_equal(0, len(l.items))
1930
1931    call g:Xsetlist([], 'r', {'title' : 'TestTitle'})
1932    call g:Xsetlist([], 'r', {'items' : [{'filename' : 'F1', 'lnum' : 10, 'text' : 'L10'}]})
1933    call g:Xsetlist([], 'r', {'items' : [{'filename' : 'F1', 'lnum' : 10, 'text' : 'L10'}]})
1934    call assert_equal('TestTitle', g:Xgetlist({'title' : 1}).title)
1935
1936    " The following used to crash Vim with address sanitizer
1937    call g:Xsetlist([], 'f')
1938    call g:Xsetlist([], 'a', {'items' : [{'filename':'F1', 'lnum':10}]})
1939    call assert_equal(10, g:Xgetlist({'items':1}).items[0].lnum)
1940
1941    " Save and restore the quickfix stack
1942    call g:Xsetlist([], 'f')
1943    call assert_equal(0, g:Xgetlist({'nr':'$'}).nr)
1944    Xexpr "File1:10:Line1"
1945    Xexpr "File2:20:Line2"
1946    Xexpr "File3:30:Line3"
1947    let last_qf = g:Xgetlist({'nr':'$'}).nr
1948    call assert_equal(3, last_qf)
1949    let qstack = []
1950    for i in range(1, last_qf)
1951	let qstack = add(qstack, g:Xgetlist({'nr':i, 'all':1}))
1952    endfor
1953    call g:Xsetlist([], 'f')
1954    for i in range(len(qstack))
1955	call g:Xsetlist([], ' ', qstack[i])
1956    endfor
1957    call assert_equal(3, g:Xgetlist({'nr':'$'}).nr)
1958    call assert_equal(10, g:Xgetlist({'nr':1, 'items':1}).items[0].lnum)
1959    call assert_equal(20, g:Xgetlist({'nr':2, 'items':1}).items[0].lnum)
1960    call assert_equal(30, g:Xgetlist({'nr':3, 'items':1}).items[0].lnum)
1961    call g:Xsetlist([], 'f')
1962
1963    " Swap two quickfix lists
1964    Xexpr "File1:10:Line10"
1965    Xexpr "File2:20:Line20"
1966    Xexpr "File3:30:Line30"
1967    call g:Xsetlist([], 'r', {'nr':1,'title':'Colors','context':['Colors']})
1968    call g:Xsetlist([], 'r', {'nr':2,'title':'Fruits','context':['Fruits']})
1969    let l1=g:Xgetlist({'nr':1,'all':1})
1970    let l2=g:Xgetlist({'nr':2,'all':1})
1971    let save_id = l1.id
1972    let l1.id=l2.id
1973    let l2.id=save_id
1974    call g:Xsetlist([], 'r', l1)
1975    call g:Xsetlist([], 'r', l2)
1976    let newl1=g:Xgetlist({'nr':1,'all':1})
1977    let newl2=g:Xgetlist({'nr':2,'all':1})
1978    call assert_equal('Fruits', newl1.title)
1979    call assert_equal(['Fruits'], newl1.context)
1980    call assert_equal('Line20', newl1.items[0].text)
1981    call assert_equal('Colors', newl2.title)
1982    call assert_equal(['Colors'], newl2.context)
1983    call assert_equal('Line10', newl2.items[0].text)
1984    call g:Xsetlist([], 'f')
1985endfunc
1986
1987func Test_qf_property()
1988    call Xproperty_tests('c')
1989    call Xproperty_tests('l')
1990endfunc
1991
1992" Tests for the QuickFixCmdPre/QuickFixCmdPost autocommands
1993func QfAutoCmdHandler(loc, cmd)
1994  call add(g:acmds, a:loc . a:cmd)
1995endfunc
1996
1997func Test_Autocmd()
1998  autocmd QuickFixCmdPre * call QfAutoCmdHandler('pre', expand('<amatch>'))
1999  autocmd QuickFixCmdPost * call QfAutoCmdHandler('post', expand('<amatch>'))
2000
2001  let g:acmds = []
2002  cexpr "F1:10:Line 10"
2003  caddexpr "F1:20:Line 20"
2004  cgetexpr "F1:30:Line 30"
2005  cexpr ""
2006  caddexpr ""
2007  cgetexpr ""
2008  silent! cexpr non_existing_func()
2009  silent! caddexpr non_existing_func()
2010  silent! cgetexpr non_existing_func()
2011  let l = ['precexpr',
2012	      \ 'postcexpr',
2013	      \ 'precaddexpr',
2014	      \ 'postcaddexpr',
2015	      \ 'precgetexpr',
2016	      \ 'postcgetexpr',
2017	      \ 'precexpr',
2018	      \ 'postcexpr',
2019	      \ 'precaddexpr',
2020	      \ 'postcaddexpr',
2021	      \ 'precgetexpr',
2022	      \ 'postcgetexpr',
2023	      \ 'precexpr',
2024	      \ 'precaddexpr',
2025	      \ 'precgetexpr']
2026  call assert_equal(l, g:acmds)
2027
2028  let g:acmds = []
2029  enew! | call append(0, "F2:10:Line 10")
2030  cbuffer!
2031  enew! | call append(0, "F2:20:Line 20")
2032  cgetbuffer
2033  enew! | call append(0, "F2:30:Line 30")
2034  caddbuffer
2035  new
2036  let bnum = bufnr('%')
2037  bunload
2038  exe 'silent! cbuffer! ' . bnum
2039  exe 'silent! cgetbuffer ' . bnum
2040  exe 'silent! caddbuffer ' . bnum
2041  enew!
2042  let l = ['precbuffer',
2043	      \ 'postcbuffer',
2044	      \ 'precgetbuffer',
2045	      \ 'postcgetbuffer',
2046	      \ 'precaddbuffer',
2047	      \ 'postcaddbuffer',
2048	      \ 'precbuffer',
2049	      \ 'precgetbuffer',
2050	      \ 'precaddbuffer']
2051  call assert_equal(l, g:acmds)
2052
2053  call writefile(['Xtest:1:Line1'], 'Xtest')
2054  call writefile([], 'Xempty')
2055  let g:acmds = []
2056  cfile Xtest
2057  caddfile Xtest
2058  cgetfile Xtest
2059  cfile Xempty
2060  caddfile Xempty
2061  cgetfile Xempty
2062  silent! cfile do_not_exist
2063  silent! caddfile do_not_exist
2064  silent! cgetfile do_not_exist
2065  let l = ['precfile',
2066	      \ 'postcfile',
2067	      \ 'precaddfile',
2068	      \ 'postcaddfile',
2069	      \ 'precgetfile',
2070	      \ 'postcgetfile',
2071	      \ 'precfile',
2072	      \ 'postcfile',
2073	      \ 'precaddfile',
2074	      \ 'postcaddfile',
2075	      \ 'precgetfile',
2076	      \ 'postcgetfile',
2077	      \ 'precfile',
2078	      \ 'postcfile',
2079	      \ 'precaddfile',
2080	      \ 'postcaddfile',
2081	      \ 'precgetfile',
2082	      \ 'postcgetfile']
2083  call assert_equal(l, g:acmds)
2084
2085  let g:acmds = []
2086  helpgrep quickfix
2087  silent! helpgrep non_existing_help_topic
2088  vimgrep test Xtest
2089  vimgrepadd test Xtest
2090  silent! vimgrep non_existing_test Xtest
2091  silent! vimgrepadd non_existing_test Xtest
2092  set makeprg=
2093  silent! make
2094  set makeprg&
2095  let l = ['prehelpgrep',
2096	      \ 'posthelpgrep',
2097	      \ 'prehelpgrep',
2098	      \ 'posthelpgrep',
2099	      \ 'previmgrep',
2100	      \ 'postvimgrep',
2101	      \ 'previmgrepadd',
2102	      \ 'postvimgrepadd',
2103	      \ 'previmgrep',
2104	      \ 'postvimgrep',
2105	      \ 'previmgrepadd',
2106	      \ 'postvimgrepadd',
2107	      \ 'premake',
2108	      \ 'postmake']
2109  call assert_equal(l, g:acmds)
2110
2111  if has('unix')
2112    " Run this test only on Unix-like systems. The grepprg may not be set on
2113    " non-Unix systems.
2114    " The following lines are used for the grep test. Don't remove.
2115    " Grep_Autocmd_Text: Match 1
2116    " GrepAdd_Autocmd_Text: Match 2
2117    let g:acmds = []
2118    silent grep Grep_Autocmd_Text test_quickfix.vim
2119    silent grepadd GrepAdd_Autocmd_Text test_quickfix.vim
2120    silent grep abc123def Xtest
2121    silent grepadd abc123def Xtest
2122    let l = ['pregrep',
2123		\ 'postgrep',
2124		\ 'pregrepadd',
2125		\ 'postgrepadd',
2126		\ 'pregrep',
2127		\ 'postgrep',
2128		\ 'pregrepadd',
2129		\ 'postgrepadd']
2130    call assert_equal(l, g:acmds)
2131  endif
2132
2133  call delete('Xtest')
2134  call delete('Xempty')
2135endfunc
2136
2137func Test_Autocmd_Exception()
2138  set efm=%m
2139  lgetexpr '?'
2140
2141  try
2142    call DoesNotExit()
2143  catch
2144    lgetexpr '1'
2145  finally
2146    lgetexpr '1'
2147  endtry
2148
2149  call assert_equal('1', getloclist(0)[0].text)
2150
2151  set efm&vim
2152endfunc
2153
2154func Test_caddbuffer_wrong()
2155  " This used to cause a memory access in freed memory.
2156  let save_efm = &efm
2157  set efm=%EEEE%m,%WWWW,%+CCCC%>%#,%GGGG%.#
2158  cgetexpr ['WWWW', 'EEEE', 'CCCC']
2159  let &efm = save_efm
2160  caddbuffer
2161  bwipe!
2162endfunc
2163
2164func Test_caddexpr_wrong()
2165  " This used to cause a memory access in freed memory.
2166  cbuffer
2167  cbuffer
2168  copen
2169  let save_efm = &efm
2170  set efm=%
2171  call assert_fails('caddexpr ""', 'E376:')
2172  let &efm = save_efm
2173endfunc
2174
2175func Test_dirstack_cleanup()
2176  " This used to cause a memory access in freed memory.
2177  let save_efm = &efm
2178  lexpr '0'
2179  lopen
2180  fun X(c)
2181    let save_efm=&efm
2182    set efm=%D%f
2183    if a:c == 'c'
2184      caddexpr '::'
2185    else
2186      laddexpr ':0:0'
2187    endif
2188    let &efm=save_efm
2189  endfun
2190  call X('c')
2191  call X('l')
2192  call setqflist([], 'r')
2193  caddbuffer
2194  let &efm = save_efm
2195endfunc
2196
2197" Tests for jumping to entries from the location list window and quickfix
2198" window
2199func Test_cwindow_jump()
2200  set efm=%f%%%l%%%m
2201  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2202  lopen | only
2203  lfirst
2204  call assert_true(winnr('$') == 2)
2205  call assert_true(winnr() == 1)
2206  " Location list for the new window should be set
2207  call assert_true(getloclist(0)[2].text == 'Line 30')
2208
2209  " Open a scratch buffer
2210  " Open a new window and create a location list
2211  " Open the location list window and close the other window
2212  " Jump to an entry.
2213  " Should create a new window and jump to the entry. The scrtach buffer
2214  " should not be used.
2215  enew | only
2216  set buftype=nofile
2217  below new
2218  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2219  lopen
2220  2wincmd c
2221  lnext
2222  call assert_true(winnr('$') == 3)
2223  call assert_true(winnr() == 2)
2224
2225  " Open two windows with two different location lists
2226  " Open the location list window and close the previous window
2227  " Jump to an entry in the location list window
2228  " Should open the file in the first window and not set the location list.
2229  enew | only
2230  lgetexpr ["F1%5%Line 5"]
2231  below new
2232  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2233  lopen
2234  2wincmd c
2235  lnext
2236  call assert_true(winnr() == 1)
2237  call assert_true(getloclist(0)[0].text == 'Line 5')
2238
2239  enew | only
2240  cgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
2241  copen
2242  cnext
2243  call assert_true(winnr('$') == 2)
2244  call assert_true(winnr() == 1)
2245
2246  enew | only
2247  set efm&vim
2248endfunc
2249
2250func XvimgrepTests(cchar)
2251  call s:setup_commands(a:cchar)
2252
2253  call writefile(['Editor:VIM vim',
2254	      \ 'Editor:Emacs EmAcS',
2255	      \ 'Editor:Notepad NOTEPAD'], 'Xtestfile1')
2256  call writefile(['Linux', 'MacOS', 'MS-Windows'], 'Xtestfile2')
2257
2258  " Error cases
2259  call assert_fails('Xvimgrep /abc *', 'E682:')
2260
2261  let @/=''
2262  call assert_fails('Xvimgrep // *', 'E35:')
2263
2264  call assert_fails('Xvimgrep abc', 'E683:')
2265  call assert_fails('Xvimgrep a1b2c3 Xtestfile1', 'E480:')
2266  call assert_fails('Xvimgrep pat Xa1b2c3', 'E480:')
2267
2268  Xexpr ""
2269  Xvimgrepadd Notepad Xtestfile1
2270  Xvimgrepadd MacOS Xtestfile2
2271  let l = g:Xgetlist()
2272  call assert_equal(2, len(l))
2273  call assert_equal('Editor:Notepad NOTEPAD', l[0].text)
2274
2275  Xvimgrep #\cvim#g Xtestfile?
2276  let l = g:Xgetlist()
2277  call assert_equal(2, len(l))
2278  call assert_equal(8, l[0].col)
2279  call assert_equal(12, l[1].col)
2280
2281  1Xvimgrep ?Editor? Xtestfile*
2282  let l = g:Xgetlist()
2283  call assert_equal(1, len(l))
2284  call assert_equal('Editor:VIM vim', l[0].text)
2285
2286  edit +3 Xtestfile2
2287  Xvimgrep +\cemacs+j Xtestfile1
2288  let l = g:Xgetlist()
2289  call assert_equal('Xtestfile2', bufname(''))
2290  call assert_equal('Editor:Emacs EmAcS', l[0].text)
2291
2292  call delete('Xtestfile1')
2293  call delete('Xtestfile2')
2294endfunc
2295
2296" Tests for the :vimgrep command
2297func Test_vimgrep()
2298  call XvimgrepTests('c')
2299  call XvimgrepTests('l')
2300endfunc
2301
2302func XfreeTests(cchar)
2303  call s:setup_commands(a:cchar)
2304
2305  enew | only
2306
2307  " Deleting the quickfix stack should work even When the current list is
2308  " somewhere in the middle of the stack
2309  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2310  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2311  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2312  Xolder
2313  call g:Xsetlist([], 'f')
2314  call assert_equal(0, len(g:Xgetlist()))
2315
2316  " After deleting the stack, adding a new list should create a stack with a
2317  " single list.
2318  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2319  call assert_equal(1, g:Xgetlist({'all':1}).nr)
2320
2321  " Deleting the stack from a quickfix window should update/clear the
2322  " quickfix/location list window.
2323  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2324  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2325  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2326  Xolder
2327  Xwindow
2328  call g:Xsetlist([], 'f')
2329  call assert_equal(2, winnr('$'))
2330  call assert_equal(1, line('$'))
2331  Xclose
2332
2333  " Deleting the stack from a non-quickfix window should update/clear the
2334  " quickfix/location list window.
2335  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2336  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
2337  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
2338  Xolder
2339  Xwindow
2340  wincmd p
2341  call g:Xsetlist([], 'f')
2342  call assert_equal(0, len(g:Xgetlist()))
2343  wincmd p
2344  call assert_equal(2, winnr('$'))
2345  call assert_equal(1, line('$'))
2346
2347  " After deleting the location list stack, if the location list window is
2348  " opened, then a new location list should be created. So opening the
2349  " location list window again should not create a new window.
2350  if a:cchar == 'l'
2351      lexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
2352      wincmd p
2353      lopen
2354      call assert_equal(2, winnr('$'))
2355  endif
2356  Xclose
2357endfunc
2358
2359" Tests for the quickfix free functionality
2360func Test_qf_free()
2361  call XfreeTests('c')
2362  call XfreeTests('l')
2363endfunc
2364
2365" Test for buffer overflow when parsing lines and adding new entries to
2366" the quickfix list.
2367func Test_bufoverflow()
2368  set efm=%f:%l:%m
2369  cgetexpr ['File1:100:' . repeat('x', 1025)]
2370
2371  set efm=%+GCompiler:\ %.%#,%f:%l:%m
2372  cgetexpr ['Compiler: ' . repeat('a', 1015), 'File1:10:Hello World']
2373
2374  set efm=%DEntering\ directory\ %f,%f:%l:%m
2375  cgetexpr ['Entering directory ' . repeat('a', 1006),
2376	      \ 'File1:10:Hello World']
2377  set efm&vim
2378endfunc
2379
2380" Tests for getting the quickfix stack size
2381func XsizeTests(cchar)
2382  call s:setup_commands(a:cchar)
2383
2384  call g:Xsetlist([], 'f')
2385  call assert_equal(0, g:Xgetlist({'nr':'$'}).nr)
2386  call assert_equal('', g:Xgetlist({'nr':'$', 'all':1}).title)
2387  call assert_equal(0, g:Xgetlist({'nr':0}).nr)
2388
2389  Xexpr "File1:10:Line1"
2390  Xexpr "File2:20:Line2"
2391  Xexpr "File3:30:Line3"
2392  Xolder | Xolder
2393  call assert_equal(3, g:Xgetlist({'nr':'$'}).nr)
2394  call g:Xsetlist([], 'f')
2395
2396  Xexpr "File1:10:Line1"
2397  Xexpr "File2:20:Line2"
2398  Xexpr "File3:30:Line3"
2399  Xolder | Xolder
2400  call g:Xsetlist([], 'a', {'nr':'$', 'title':'Compiler'})
2401  call assert_equal('Compiler', g:Xgetlist({'nr':3, 'all':1}).title)
2402endfunc
2403
2404func Test_Qf_Size()
2405  call XsizeTests('c')
2406  call XsizeTests('l')
2407endfunc
2408
2409func Test_cclose_from_copen()
2410    augroup QF_Test
2411	au!
2412        au FileType qf :call assert_fails(':cclose', 'E788')
2413    augroup END
2414    copen
2415    augroup QF_Test
2416	au!
2417    augroup END
2418    augroup! QF_Test
2419endfunc
2420
2421func Test_cclose_in_autocmd()
2422  " Problem is only triggered if "starting" is zero, so that the OptionsSet
2423  " event will be triggered.
2424  call test_override('starting', 1)
2425  augroup QF_Test
2426    au!
2427    au FileType qf :call assert_fails(':cclose', 'E788')
2428  augroup END
2429  copen
2430  augroup QF_Test
2431    au!
2432  augroup END
2433  augroup! QF_Test
2434  call test_override('starting', 0)
2435endfunc
2436
2437func Test_resize_from_copen()
2438    augroup QF_Test
2439	au!
2440        au FileType qf resize 5
2441    augroup END
2442    try
2443	" This should succeed without any exception.  No other buffers are
2444	" involved in the autocmd.
2445	copen
2446    finally
2447	augroup QF_Test
2448	    au!
2449	augroup END
2450	augroup! QF_Test
2451    endtry
2452endfunc
2453
2454" Tests for the quickfix buffer b:changedtick variable
2455func Xchangedtick_tests(cchar)
2456  call s:setup_commands(a:cchar)
2457
2458  new | only
2459
2460  Xexpr "" | Xexpr "" | Xexpr ""
2461
2462  Xopen
2463  Xolder
2464  Xolder
2465  Xaddexpr "F1:10:Line10"
2466  Xaddexpr "F2:20:Line20"
2467  call g:Xsetlist([{"filename":"F3", "lnum":30, "text":"Line30"}], 'a')
2468  call g:Xsetlist([], 'f')
2469  call assert_equal(8, getbufvar('%', 'changedtick'))
2470  Xclose
2471endfunc
2472
2473func Test_changedtick()
2474  call Xchangedtick_tests('c')
2475  call Xchangedtick_tests('l')
2476endfunc
2477
2478" Tests for parsing an expression using setqflist()
2479func Xsetexpr_tests(cchar)
2480  call s:setup_commands(a:cchar)
2481
2482  let t = ["File1:10:Line10", "File1:20:Line20"]
2483  call g:Xsetlist([], ' ', {'lines' : t})
2484  call g:Xsetlist([], 'a', {'lines' : ["File1:30:Line30"]})
2485
2486  let l = g:Xgetlist()
2487  call assert_equal(3, len(l))
2488  call assert_equal(20, l[1].lnum)
2489  call assert_equal('Line30', l[2].text)
2490  call g:Xsetlist([], 'r', {'lines' : ["File2:5:Line5"]})
2491  let l = g:Xgetlist()
2492  call assert_equal(1, len(l))
2493  call assert_equal('Line5', l[0].text)
2494  call assert_equal(-1, g:Xsetlist([], 'a', {'lines' : 10}))
2495  call assert_equal(-1, g:Xsetlist([], 'a', {'lines' : "F1:10:L10"}))
2496
2497  call g:Xsetlist([], 'f')
2498  " Add entries to multiple lists
2499  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["File1:10:Line10"]})
2500  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["File2:20:Line20"]})
2501  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["File1:15:Line15"]})
2502  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["File2:25:Line25"]})
2503  call assert_equal('Line15', g:Xgetlist({'nr':1, 'items':1}).items[1].text)
2504  call assert_equal('Line25', g:Xgetlist({'nr':2, 'items':1}).items[1].text)
2505
2506  " Adding entries using a custom efm
2507  set efm&
2508  call g:Xsetlist([], ' ', {'efm' : '%f#%l#%m',
2509				\ 'lines' : ["F1#10#L10", "F2#20#L20"]})
2510  call assert_equal(20, g:Xgetlist({'items':1}).items[1].lnum)
2511  call g:Xsetlist([], 'a', {'efm' : '%f#%l#%m', 'lines' : ["F3:30:L30"]})
2512  call assert_equal('F3:30:L30', g:Xgetlist({'items':1}).items[2].text)
2513  call assert_equal(20, g:Xgetlist({'items':1}).items[1].lnum)
2514  call assert_equal(-1, g:Xsetlist([], 'a', {'efm' : [],
2515				\ 'lines' : ['F1:10:L10']}))
2516endfunc
2517
2518func Test_setexpr()
2519  call Xsetexpr_tests('c')
2520  call Xsetexpr_tests('l')
2521endfunc
2522
2523" Tests for per quickfix/location list directory stack
2524func Xmultidirstack_tests(cchar)
2525  call s:setup_commands(a:cchar)
2526
2527  call g:Xsetlist([], 'f')
2528  Xexpr "" | Xexpr ""
2529
2530  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["Entering dir 'Xone/a'"]})
2531  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["Entering dir 'Xtwo/a'"]})
2532  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["one.txt:3:one one one"]})
2533  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["two.txt:5:two two two"]})
2534
2535  let l1 = g:Xgetlist({'nr':1, 'items':1})
2536  let l2 = g:Xgetlist({'nr':2, 'items':1})
2537  call assert_equal('Xone/a/one.txt', bufname(l1.items[1].bufnr))
2538  call assert_equal(3, l1.items[1].lnum)
2539  call assert_equal('Xtwo/a/two.txt', bufname(l2.items[1].bufnr))
2540  call assert_equal(5, l2.items[1].lnum)
2541endfunc
2542
2543func Test_multidirstack()
2544  call mkdir('Xone/a', 'p')
2545  call mkdir('Xtwo/a', 'p')
2546  let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7']
2547  call writefile(lines, 'Xone/a/one.txt')
2548  call writefile(lines, 'Xtwo/a/two.txt')
2549  let save_efm = &efm
2550  set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f'
2551
2552  call Xmultidirstack_tests('c')
2553  call Xmultidirstack_tests('l')
2554
2555  let &efm = save_efm
2556  call delete('Xone', 'rf')
2557  call delete('Xtwo', 'rf')
2558endfunc
2559
2560" Tests for per quickfix/location list file stack
2561func Xmultifilestack_tests(cchar)
2562  call s:setup_commands(a:cchar)
2563
2564  call g:Xsetlist([], 'f')
2565  Xexpr "" | Xexpr ""
2566
2567  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["[one.txt]"]})
2568  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["[two.txt]"]})
2569  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["(3,5) one one one"]})
2570  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["(5,9) two two two"]})
2571
2572  let l1 = g:Xgetlist({'nr':1, 'items':1})
2573  let l2 = g:Xgetlist({'nr':2, 'items':1})
2574  call assert_equal('one.txt', bufname(l1.items[1].bufnr))
2575  call assert_equal(3, l1.items[1].lnum)
2576  call assert_equal('two.txt', bufname(l2.items[1].bufnr))
2577  call assert_equal(5, l2.items[1].lnum)
2578endfunc
2579
2580func Test_multifilestack()
2581  let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7']
2582  call writefile(lines, 'one.txt')
2583  call writefile(lines, 'two.txt')
2584  let save_efm = &efm
2585  set efm=%+P[%f],(%l\\,%c)\ %m,%-Q
2586
2587  call Xmultifilestack_tests('c')
2588  call Xmultifilestack_tests('l')
2589
2590  let &efm = save_efm
2591  call delete('one.txt')
2592  call delete('two.txt')
2593endfunc
2594
2595" Tests for per buffer 'efm' setting
2596func Test_perbuf_efm()
2597  call writefile(["File1-10-Line10"], 'one.txt')
2598  call writefile(["File2#20#Line20"], 'two.txt')
2599  set efm=%f#%l#%m
2600  new | only
2601  new
2602  setlocal efm=%f-%l-%m
2603  cfile one.txt
2604  wincmd w
2605  caddfile two.txt
2606
2607  let l = getqflist()
2608  call assert_equal(10, l[0].lnum)
2609  call assert_equal('Line20', l[1].text)
2610
2611  set efm&
2612  new | only
2613  call delete('one.txt')
2614  call delete('two.txt')
2615endfunc
2616
2617" Open multiple help windows using ":lhelpgrep
2618" This test used to crash Vim
2619func Test_Multi_LL_Help()
2620    new | only
2621    lhelpgrep window
2622    lopen
2623    e#
2624    lhelpgrep buffer
2625    call assert_equal(3, winnr('$'))
2626    call assert_true(len(getloclist(1)) != 0)
2627    call assert_true(len(getloclist(2)) != 0)
2628    new | only
2629endfunc
2630
2631" Tests for adding new quickfix lists using setqflist()
2632func XaddQf_tests(cchar)
2633  call s:setup_commands(a:cchar)
2634
2635  " Create a new list using ' ' for action
2636  call g:Xsetlist([], 'f')
2637  call g:Xsetlist([], ' ', {'title' : 'Test1'})
2638  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2639  call assert_equal(1, l.nr)
2640  call assert_equal('Test1', l.title)
2641
2642  " Create a new list using ' ' for action and '$' for 'nr'
2643  call g:Xsetlist([], 'f')
2644  call g:Xsetlist([], ' ', {'title' : 'Test2', 'nr' : '$'})
2645  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2646  call assert_equal(1, l.nr)
2647  call assert_equal('Test2', l.title)
2648
2649  " Create a new list using 'a' for action
2650  call g:Xsetlist([], 'f')
2651  call g:Xsetlist([], 'a', {'title' : 'Test3'})
2652  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2653  call assert_equal(1, l.nr)
2654  call assert_equal('Test3', l.title)
2655
2656  " Create a new list using 'a' for action and '$' for 'nr'
2657  call g:Xsetlist([], 'f')
2658  call g:Xsetlist([], 'a', {'title' : 'Test3', 'nr' : '$'})
2659  call g:Xsetlist([], 'a', {'title' : 'Test4'})
2660  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2661  call assert_equal(1, l.nr)
2662  call assert_equal('Test4', l.title)
2663
2664  " Adding a quickfix list should remove all the lists following the current
2665  " list.
2666  Xexpr "" | Xexpr "" | Xexpr ""
2667  silent! 10Xolder
2668  call g:Xsetlist([], ' ', {'title' : 'Test5'})
2669  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2670  call assert_equal(2, l.nr)
2671  call assert_equal('Test5', l.title)
2672
2673  " Add a quickfix list using '$' as the list number.
2674  let lastqf = g:Xgetlist({'nr':'$'}).nr
2675  silent! 99Xolder
2676  call g:Xsetlist([], ' ', {'nr' : '$', 'title' : 'Test6'})
2677  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2678  call assert_equal(lastqf + 1, l.nr)
2679  call assert_equal('Test6', l.title)
2680
2681  " Add a quickfix list using 'nr' set to one more than the quickfix
2682  " list size.
2683  let lastqf = g:Xgetlist({'nr':'$'}).nr
2684  silent! 99Xolder
2685  call g:Xsetlist([], ' ', {'nr' : lastqf + 1, 'title' : 'Test7'})
2686  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2687  call assert_equal(lastqf + 1, l.nr)
2688  call assert_equal('Test7', l.title)
2689
2690  " Add a quickfix list to a stack with 10 lists using 'nr' set to '$'
2691  exe repeat('Xexpr "" |', 9) . 'Xexpr ""'
2692  silent! 99Xolder
2693  call g:Xsetlist([], ' ', {'nr' : '$', 'title' : 'Test8'})
2694  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
2695  call assert_equal(10, l.nr)
2696  call assert_equal('Test8', l.title)
2697
2698  " Add a quickfix list using 'nr' set to a value greater than 10
2699  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : 12, 'title' : 'Test9'}))
2700
2701  " Try adding a quickfix list with 'nr' set to a value greater than the
2702  " quickfix list size but less than 10.
2703  call g:Xsetlist([], 'f')
2704  Xexpr "" | Xexpr "" | Xexpr ""
2705  silent! 99Xolder
2706  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : 8, 'title' : 'Test10'}))
2707
2708  " Add a quickfix list using 'nr' set to a some string or list
2709  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : [1,2], 'title' : 'Test11'}))
2710endfunc
2711
2712func Test_add_qf()
2713  call XaddQf_tests('c')
2714  call XaddQf_tests('l')
2715endfunc
2716
2717" Test for getting the quickfix list items from some text without modifying
2718" the quickfix stack
2719func XgetListFromLines(cchar)
2720  call s:setup_commands(a:cchar)
2721  call g:Xsetlist([], 'f')
2722
2723  let l = g:Xgetlist({'lines' : ["File2:20:Line20", "File2:30:Line30"]}).items
2724  call assert_equal(2, len(l))
2725  call assert_equal(30, l[1].lnum)
2726
2727  call assert_equal({}, g:Xgetlist({'lines' : 10}))
2728  call assert_equal({}, g:Xgetlist({'lines' : 'File1:10:Line10'}))
2729  call assert_equal([], g:Xgetlist({'lines' : []}).items)
2730  call assert_equal([], g:Xgetlist({'lines' : [10, 20]}).items)
2731
2732  " Parse text using a custom efm
2733  set efm&
2734  let l = g:Xgetlist({'lines':['File3#30#Line30'], 'efm' : '%f#%l#%m'}).items
2735  call assert_equal('Line30', l[0].text)
2736  let l = g:Xgetlist({'lines':['File3:30:Line30'], 'efm' : '%f-%l-%m'}).items
2737  call assert_equal('File3:30:Line30', l[0].text)
2738  let l = g:Xgetlist({'lines':['File3:30:Line30'], 'efm' : [1,2]})
2739  call assert_equal({}, l)
2740  call assert_fails("call g:Xgetlist({'lines':['abc'], 'efm':'%2'})", 'E376:')
2741  call assert_fails("call g:Xgetlist({'lines':['abc'], 'efm':''})", 'E378:')
2742
2743  " Make sure that the quickfix stack is not modified
2744  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
2745endfunc
2746
2747func Test_get_list_from_lines()
2748  call XgetListFromLines('c')
2749  call XgetListFromLines('l')
2750endfunc
2751
2752" Tests for the quickfix list id
2753func Xqfid_tests(cchar)
2754  call s:setup_commands(a:cchar)
2755
2756  call g:Xsetlist([], 'f')
2757  call assert_equal(0, g:Xgetlist({'id':0}).id)
2758  Xexpr ''
2759  let start_id = g:Xgetlist({'id' : 0}).id
2760  Xexpr '' | Xexpr ''
2761  Xolder
2762  call assert_equal(start_id, g:Xgetlist({'id':0, 'nr':1}).id)
2763  call assert_equal(start_id + 1, g:Xgetlist({'id':0, 'nr':0}).id)
2764  call assert_equal(start_id + 2, g:Xgetlist({'id':0, 'nr':'$'}).id)
2765  call assert_equal(0, g:Xgetlist({'id':0, 'nr':99}).id)
2766  call assert_equal(2, g:Xgetlist({'id':start_id + 1, 'nr':0}).nr)
2767  call assert_equal(0, g:Xgetlist({'id':99, 'nr':0}).id)
2768  call assert_equal(0, g:Xgetlist({'id':"abc", 'nr':0}).id)
2769
2770  call g:Xsetlist([], 'a', {'id':start_id, 'context':[1,2]})
2771  call assert_equal([1,2], g:Xgetlist({'nr':1, 'context':1}).context)
2772  call g:Xsetlist([], 'a', {'id':start_id+1, 'lines':['F1:10:L10']})
2773  call assert_equal('L10', g:Xgetlist({'nr':2, 'items':1}).items[0].text)
2774  call assert_equal(-1, g:Xsetlist([], 'a', {'id':999, 'title':'Vim'}))
2775  call assert_equal(-1, g:Xsetlist([], 'a', {'id':'abc', 'title':'Vim'}))
2776
2777  let qfid = g:Xgetlist({'id':0, 'nr':0})
2778  call g:Xsetlist([], 'f')
2779  call assert_equal(0, g:Xgetlist({'id':qfid, 'nr':0}).id)
2780endfunc
2781
2782func Test_qf_id()
2783  call Xqfid_tests('c')
2784  call Xqfid_tests('l')
2785endfunc
2786
2787func Xqfjump_tests(cchar)
2788  call s:setup_commands(a:cchar)
2789
2790  call writefile(["Line1\tFoo", "Line2"], 'F1')
2791  call writefile(["Line1\tBar", "Line2"], 'F2')
2792  call writefile(["Line1\tBaz", "Line2"], 'F3')
2793
2794  call g:Xsetlist([], 'f')
2795
2796  " Tests for
2797  "   Jumping to a line using a pattern
2798  "   Jumping to a column greater than the last column in a line
2799  "   Jumping to a line greater than the last line in the file
2800  let l = []
2801  for i in range(1, 7)
2802    call add(l, {})
2803  endfor
2804  let l[0].filename='F1'
2805  let l[0].pattern='Line1'
2806  let l[1].filename='F2'
2807  let l[1].pattern='Line1'
2808  let l[2].filename='F3'
2809  let l[2].pattern='Line1'
2810  let l[3].filename='F3'
2811  let l[3].lnum=1
2812  let l[3].col=9
2813  let l[3].vcol=1
2814  let l[4].filename='F3'
2815  let l[4].lnum=99
2816  let l[5].filename='F3'
2817  let l[5].lnum=1
2818  let l[5].col=99
2819  let l[5].vcol=1
2820  let l[6].filename='F3'
2821  let l[6].pattern='abcxyz'
2822
2823  call g:Xsetlist([], ' ', {'items' : l})
2824  Xopen | only
2825  2Xnext
2826  call assert_equal(3, g:Xgetlist({'idx' : 0}).idx)
2827  call assert_equal('F3', bufname('%'))
2828  Xnext
2829  call assert_equal(7, col('.'))
2830  Xnext
2831  call assert_equal(2, line('.'))
2832  Xnext
2833  call assert_equal(9, col('.'))
2834  2
2835  Xnext
2836  call assert_equal(2, line('.'))
2837
2838  if a:cchar == 'l'
2839    " When jumping to a location list entry in the location list window and
2840    " no usable windows are available, then a new window should be opened.
2841    enew! | new | only
2842    call g:Xsetlist([], 'f')
2843    setlocal buftype=nofile
2844    new
2845    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']})
2846    Xopen
2847    let winid = win_getid()
2848    wincmd p
2849    close
2850    call win_gotoid(winid)
2851    Xnext
2852    call assert_equal(3, winnr('$'))
2853    call assert_equal(1, winnr())
2854    call assert_equal(2, line('.'))
2855
2856    " When jumping to an entry in the location list window and the window
2857    " associated with the location list is not present and a window containing
2858    " the file is already present, then that window should be used.
2859    close
2860    belowright new
2861    call g:Xsetlist([], 'f')
2862    edit F3
2863    call win_gotoid(winid)
2864    Xlast
2865    call assert_equal(3, winnr())
2866    call assert_equal(6, g:Xgetlist({'size' : 1}).size)
2867    call assert_equal(winid, g:Xgetlist({'winid' : 1}).winid)
2868  endif
2869
2870  " Cleanup
2871  enew!
2872  new | only
2873
2874  call delete('F1')
2875  call delete('F2')
2876  call delete('F3')
2877endfunc
2878
2879func Test_qfjump()
2880  call Xqfjump_tests('c')
2881  call Xqfjump_tests('l')
2882endfunc
2883
2884" Tests for the getqflist() and getloclist() functions when the list is not
2885" present or is empty
2886func Xgetlist_empty_tests(cchar)
2887  call s:setup_commands(a:cchar)
2888
2889  " Empty quickfix stack
2890  call g:Xsetlist([], 'f')
2891  call assert_equal('', g:Xgetlist({'context' : 0}).context)
2892  call assert_equal(0, g:Xgetlist({'id' : 0}).id)
2893  call assert_equal(0, g:Xgetlist({'idx' : 0}).idx)
2894  call assert_equal([], g:Xgetlist({'items' : 0}).items)
2895  call assert_equal(0, g:Xgetlist({'nr' : 0}).nr)
2896  call assert_equal(0, g:Xgetlist({'size' : 0}).size)
2897  call assert_equal('', g:Xgetlist({'title' : 0}).title)
2898  call assert_equal(0, g:Xgetlist({'winid' : 0}).winid)
2899  call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [], 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0}, g:Xgetlist({'all' : 0}))
2900
2901  " Empty quickfix list
2902  Xexpr ""
2903  call assert_equal('', g:Xgetlist({'context' : 0}).context)
2904  call assert_notequal(0, g:Xgetlist({'id' : 0}).id)
2905  call assert_equal(0, g:Xgetlist({'idx' : 0}).idx)
2906  call assert_equal([], g:Xgetlist({'items' : 0}).items)
2907  call assert_notequal(0, g:Xgetlist({'nr' : 0}).nr)
2908  call assert_equal(0, g:Xgetlist({'size' : 0}).size)
2909  call assert_notequal('', g:Xgetlist({'title' : 0}).title)
2910  call assert_equal(0, g:Xgetlist({'winid' : 0}).winid)
2911
2912  let qfid = g:Xgetlist({'id' : 0}).id
2913  call g:Xsetlist([], 'f')
2914
2915  " Non-existing quickfix identifier
2916  call assert_equal('', g:Xgetlist({'id' : qfid, 'context' : 0}).context)
2917  call assert_equal(0, g:Xgetlist({'id' : qfid}).id)
2918  call assert_equal(0, g:Xgetlist({'id' : qfid, 'idx' : 0}).idx)
2919  call assert_equal([], g:Xgetlist({'id' : qfid, 'items' : 0}).items)
2920  call assert_equal(0, g:Xgetlist({'id' : qfid, 'nr' : 0}).nr)
2921  call assert_equal(0, g:Xgetlist({'id' : qfid, 'size' : 0}).size)
2922  call assert_equal('', g:Xgetlist({'id' : qfid, 'title' : 0}).title)
2923  call assert_equal(0, g:Xgetlist({'id' : qfid, 'winid' : 0}).winid)
2924  call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [], 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0}, g:Xgetlist({'id' : qfid, 'all' : 0}))
2925
2926  " Non-existing quickfix list number
2927  call assert_equal('', g:Xgetlist({'nr' : 5, 'context' : 0}).context)
2928  call assert_equal(0, g:Xgetlist({'nr' : 5}).nr)
2929  call assert_equal(0, g:Xgetlist({'nr' : 5, 'idx' : 0}).idx)
2930  call assert_equal([], g:Xgetlist({'nr' : 5, 'items' : 0}).items)
2931  call assert_equal(0, g:Xgetlist({'nr' : 5, 'id' : 0}).id)
2932  call assert_equal(0, g:Xgetlist({'nr' : 5, 'size' : 0}).size)
2933  call assert_equal('', g:Xgetlist({'nr' : 5, 'title' : 0}).title)
2934  call assert_equal(0, g:Xgetlist({'nr' : 5, 'winid' : 0}).winid)
2935  call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [], 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0}, g:Xgetlist({'nr' : 5, 'all' : 0}))
2936endfunc
2937
2938func Test_getqflist()
2939  call Xgetlist_empty_tests('c')
2940  call Xgetlist_empty_tests('l')
2941endfunc
2942