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