1" Test for the quickfix commands.
2
3if !has('quickfix')
4  finish
5endif
6
7" Tests for the :clist and :llist commands
8function XlistTests(cchar)
9  let Xlist = a:cchar . 'list'
10  let Xgetexpr = a:cchar . 'getexpr'
11
12  " With an empty list, command should return error
13  exe Xgetexpr . ' []'
14  exe 'silent! ' . Xlist
15  call assert_true(v:errmsg ==# 'E42: No Errors')
16
17  " Populate the list and then try
18  exe Xgetexpr . " ['non-error 1', 'Xtestfile1:1:3:Line1',
19		  \ 'non-error 2', 'Xtestfile2:2:2:Line2',
20		  \ 'non-error 3', 'Xtestfile3:3:1:Line3']"
21
22  " List only valid entries
23  redir => result
24  exe Xlist
25  redir END
26  let l = split(result, "\n")
27  call assert_equal([' 2 Xtestfile1:1 col 3: Line1',
28		   \ ' 4 Xtestfile2:2 col 2: Line2',
29		   \ ' 6 Xtestfile3:3 col 1: Line3'], l)
30
31  " List all the entries
32  redir => result
33  exe Xlist . "!"
34  redir END
35  let l = split(result, "\n")
36  call assert_equal([' 1: non-error 1', ' 2 Xtestfile1:1 col 3: Line1',
37		   \ ' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2',
38		   \ ' 5: non-error 3', ' 6 Xtestfile3:3 col 1: Line3'], l)
39
40  " List a range of errors
41  redir => result
42  exe Xlist . " 3,6"
43  redir END
44  let l = split(result, "\n")
45  call assert_equal([' 4 Xtestfile2:2 col 2: Line2',
46		   \ ' 6 Xtestfile3:3 col 1: Line3'], l)
47
48  redir => result
49  exe Xlist . "! 3,4"
50  redir END
51  let l = split(result, "\n")
52  call assert_equal([' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2'], l)
53
54  redir => result
55  exe Xlist . " -6,-4"
56  redir END
57  let l = split(result, "\n")
58  call assert_equal([' 2 Xtestfile1:1 col 3: Line1'], l)
59
60  redir => result
61  exe Xlist . "! -5,-3"
62  redir END
63  let l = split(result, "\n")
64  call assert_equal([' 2 Xtestfile1:1 col 3: Line1',
65		   \ ' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2'], l)
66endfunction
67
68function Test_clist()
69  call XlistTests('c')
70  call XlistTests('l')
71endfunction
72
73" Tests for the :colder, :cnewer, :lolder and :lnewer commands
74" Note that this test assumes that a quickfix/location list is
75" already set by the caller.
76function XageTests(cchar)
77  let Xolder = a:cchar . 'older'
78  let Xnewer = a:cchar . 'newer'
79  let Xgetexpr = a:cchar . 'getexpr'
80  if a:cchar == 'c'
81    let Xgetlist = 'getqflist()'
82  else
83    let Xgetlist = 'getloclist(0)'
84  endif
85
86  " Jumping to a non existent list should return error
87  exe 'silent! ' . Xolder . ' 99'
88  call assert_true(v:errmsg ==# 'E380: At bottom of quickfix stack')
89
90  exe 'silent! ' . Xnewer . ' 99'
91  call assert_true(v:errmsg ==# 'E381: At top of quickfix stack')
92
93  " Add three quickfix/location lists
94  exe Xgetexpr . " ['Xtestfile1:1:3:Line1']"
95  exe Xgetexpr . " ['Xtestfile2:2:2:Line2']"
96  exe Xgetexpr . " ['Xtestfile3:3:1:Line3']"
97
98  " Go back two lists
99  exe Xolder
100  exe 'let l = ' . Xgetlist
101  call assert_equal('Line2', l[0].text)
102
103  " Go forward two lists
104  exe Xnewer
105  exe 'let l = ' . Xgetlist
106  call assert_equal('Line3', l[0].text)
107
108  " Test for the optional count argument
109  exe Xolder . ' 2'
110  exe 'let l = ' . Xgetlist
111  call assert_equal('Line1', l[0].text)
112
113  exe Xnewer . ' 2'
114  exe 'let l = ' . Xgetlist
115  call assert_equal('Line3', l[0].text)
116endfunction
117
118function Test_cage()
119  let list = [{'bufnr': 1, 'lnum': 1}]
120  call setqflist(list)
121  call XageTests('c')
122
123  call setloclist(0, list)
124  call XageTests('l')
125endfunction
126
127" Tests for the :cwindow, :lwindow :cclose, :lclose, :copen and :lopen
128" commands
129function XwindowTests(cchar)
130  let Xwindow = a:cchar . 'window'
131  let Xclose = a:cchar . 'close'
132  let Xopen = a:cchar . 'open'
133  let Xgetexpr = a:cchar . 'getexpr'
134
135  " Create a list with no valid entries
136  exe Xgetexpr . " ['non-error 1', 'non-error 2', 'non-error 3']"
137
138  " Quickfix/Location window should not open with no valid errors
139  exe Xwindow
140  call assert_true(winnr('$') == 1)
141
142  " Create a list with valid entries
143  exe Xgetexpr . " ['Xtestfile1:1:3:Line1', 'Xtestfile2:2:2:Line2',
144		  \ 'Xtestfile3:3:1:Line3']"
145
146  " Open the window
147  exe Xwindow
148  call assert_true(winnr('$') == 2 && winnr() == 2 &&
149	\ getline('.') ==# 'Xtestfile1|1 col 3| Line1')
150
151  " Close the window
152  exe Xclose
153  call assert_true(winnr('$') == 1)
154
155  " Create a list with no valid entries
156  exe Xgetexpr . " ['non-error 1', 'non-error 2', 'non-error 3']"
157
158  " Open the window
159  exe Xopen . ' 5'
160  call assert_true(winnr('$') == 2 && getline('.') ==# '|| non-error 1'
161		      \  && winheight('.') == 5)
162
163  " Opening the window again, should move the cursor to that window
164  wincmd t
165  exe Xopen . ' 7'
166  call assert_true(winnr('$') == 2 && winnr() == 2 &&
167	\ winheight('.') == 7 &&
168	\ getline('.') ==# '|| non-error 1')
169
170
171  " Calling cwindow should close the quickfix window with no valid errors
172  exe Xwindow
173  call assert_true(winnr('$') == 1)
174endfunction
175
176function Test_cwindow()
177  call XwindowTests('c')
178  call XwindowTests('l')
179endfunction
180
181" Tests for the :cfile, :lfile, :caddfile, :laddfile, :cgetfile and :lgetfile
182" commands.
183function XfileTests(cchar)
184  let Xfile = a:cchar . 'file'
185  let Xgetfile = a:cchar . 'getfile'
186  let Xaddfile = a:cchar . 'addfile'
187  if a:cchar == 'c'
188    let Xgetlist = 'getqflist()'
189  else
190    let Xgetlist = 'getloclist(0)'
191  endif
192
193  call writefile(['Xtestfile1:700:10:Line 700',
194	\ 'Xtestfile2:800:15:Line 800'], 'Xqftestfile1')
195
196  enew!
197  exe Xfile . ' Xqftestfile1'
198  exe 'let l = ' . Xgetlist
199  call assert_true(len(l) == 2 &&
200	\ l[0].lnum == 700 && l[0].col == 10 && l[0].text ==# 'Line 700' &&
201	\ l[1].lnum == 800 && l[1].col == 15 && l[1].text ==# 'Line 800')
202
203  " Run cfile/lfile from a modified buffer
204  enew!
205  silent! put ='Quickfix'
206  exe 'silent! ' . Xfile . ' Xqftestfile1'
207  call assert_true(v:errmsg ==# 'E37: No write since last change (add ! to override)')
208
209  call writefile(['Xtestfile3:900:30:Line 900'], 'Xqftestfile1')
210  exe Xaddfile . ' Xqftestfile1'
211  exe 'let l = ' . Xgetlist
212  call assert_true(len(l) == 3 &&
213	\ l[2].lnum == 900 && l[2].col == 30 && l[2].text ==# 'Line 900')
214
215  call writefile(['Xtestfile1:222:77:Line 222',
216	\ 'Xtestfile2:333:88:Line 333'], 'Xqftestfile1')
217
218  enew!
219  exe Xgetfile . ' Xqftestfile1'
220  exe 'let l = ' . Xgetlist
221  call assert_true(len(l) == 2 &&
222	\ l[0].lnum == 222 && l[0].col == 77 && l[0].text ==# 'Line 222' &&
223	\ l[1].lnum == 333 && l[1].col == 88 && l[1].text ==# 'Line 333')
224
225  call delete('Xqftestfile1')
226endfunction
227
228function Test_cfile()
229  call XfileTests('c')
230  call XfileTests('l')
231endfunction
232
233" Tests for the :cbuffer, :lbuffer, :caddbuffer, :laddbuffer, :cgetbuffer and
234" :lgetbuffer commands.
235function XbufferTests(cchar)
236  let Xbuffer = a:cchar . 'buffer'
237  let Xgetbuffer = a:cchar . 'getbuffer'
238  let Xaddbuffer = a:cchar . 'addbuffer'
239  if a:cchar == 'c'
240    let Xgetlist = 'getqflist()'
241  else
242    let Xgetlist = 'getloclist(0)'
243  endif
244
245  enew!
246  silent! call setline(1, ['Xtestfile7:700:10:Line 700',
247	\ 'Xtestfile8:800:15:Line 800'])
248  exe Xbuffer . "!"
249  exe 'let l = ' . Xgetlist
250  call assert_true(len(l) == 2 &&
251	\ l[0].lnum == 700 && l[0].col == 10 && l[0].text ==# 'Line 700' &&
252	\ l[1].lnum == 800 && l[1].col == 15 && l[1].text ==# 'Line 800')
253
254  enew!
255  silent! call setline(1, ['Xtestfile9:900:55:Line 900',
256	\ 'Xtestfile10:950:66:Line 950'])
257  exe Xgetbuffer
258  exe 'let l = ' . Xgetlist
259  call assert_true(len(l) == 2 &&
260	\ l[0].lnum == 900 && l[0].col == 55 && l[0].text ==# 'Line 900' &&
261	\ l[1].lnum == 950 && l[1].col == 66 && l[1].text ==# 'Line 950')
262
263  enew!
264  silent! call setline(1, ['Xtestfile11:700:20:Line 700',
265	\ 'Xtestfile12:750:25:Line 750'])
266  exe Xaddbuffer
267  exe 'let l = ' . Xgetlist
268  call assert_true(len(l) == 4 &&
269	\ l[1].lnum == 950 && l[1].col == 66 && l[1].text ==# 'Line 950' &&
270	\ l[2].lnum == 700 && l[2].col == 20 && l[2].text ==# 'Line 700' &&
271	\ l[3].lnum == 750 && l[3].col == 25 && l[3].text ==# 'Line 750')
272
273endfunction
274
275function Test_cbuffer()
276  call XbufferTests('c')
277  call XbufferTests('l')
278endfunction
279
280function Test_nomem()
281  call alloc_fail(GetAllocId('qf_dirname_start'), 0, 0)
282  call assert_fails('vimgrep vim runtest.vim', 'E342:')
283
284  call alloc_fail(GetAllocId('qf_dirname_now'), 0, 0)
285  call assert_fails('vimgrep vim runtest.vim', 'E342:')
286
287  call alloc_fail(GetAllocId('qf_namebuf'), 0, 0)
288  call assert_fails('cfile runtest.vim', 'E342:')
289
290  call alloc_fail(GetAllocId('qf_errmsg'), 0, 0)
291  call assert_fails('cfile runtest.vim', 'E342:')
292
293  call alloc_fail(GetAllocId('qf_pattern'), 0, 0)
294  call assert_fails('cfile runtest.vim', 'E342:')
295
296endfunc
297
298function Test_helpgrep()
299  helpgrep quickfix
300  copen
301  " This wipes out the buffer, make sure that doesn't cause trouble.
302  cclose
303endfunc
304
305func Test_errortitle()
306  augroup QfBufWinEnter
307    au!
308    au BufWinEnter * :let g:a=get(w:, 'quickfix_title', 'NONE')
309  augroup END
310  copen
311  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'')'}]
312  call setqflist(a)
313  call assert_equal(':setqflist()', g:a)
314  augroup QfBufWinEnter
315    au!
316  augroup END
317  augroup! QfBufWinEnter
318endfunc
319
320func Test_vimgreptitle()
321  augroup QfBufWinEnter
322    au!
323    au BufWinEnter * :let g:a=get(w:, 'quickfix_title', 'NONE')
324  augroup END
325  try
326    vimgrep /pattern/j file
327  catch /E480/
328  endtry
329  copen
330  call assert_equal(':    vimgrep /pattern/j file', g:a)
331  augroup QfBufWinEnter
332    au!
333  augroup END
334  augroup! QfBufWinEnter
335endfunc
336
337function XqfTitleTests(cchar)
338  let Xgetexpr = a:cchar . 'getexpr'
339  if a:cchar == 'c'
340    let Xgetlist = 'getqflist()'
341  else
342    let Xgetlist = 'getloclist(0)'
343  endif
344  let Xopen = a:cchar . 'open'
345  let Xclose = a:cchar . 'close'
346
347  exe Xgetexpr . " ['file:1:1:message']"
348  exe 'let l = ' . Xgetlist
349  if a:cchar == 'c'
350    call setqflist(l, 'r')
351  else
352    call setloclist(0, l, 'r')
353  endif
354
355  exe Xopen
356  if a:cchar == 'c'
357    let title = ':setqflist()'
358  else
359    let title = ':setloclist()'
360  endif
361  call assert_equal(title, w:quickfix_title)
362  exe Xclose
363endfunction
364
365" Tests for quickfix window's title
366function Test_qf_title()
367    call XqfTitleTests('c')
368    call XqfTitleTests('l')
369endfunction
370
371" Tests for 'errorformat'
372function Test_efm()
373  let save_efm = &efm
374  set efm=%EEEE%m,%WWWW%m,%+CCCC%.%#,%-GGGG%.%#
375  cgetexpr ['WWWW', 'EEEE', 'CCCC']
376  let l = strtrans(string(map(getqflist(), '[v:val.text, v:val.valid]')))
377  call assert_equal("[['W', 1], ['E^@CCCC', 1]]", l)
378  cgetexpr ['WWWW', 'GGGG', 'EEEE', 'CCCC']
379  let l = strtrans(string(map(getqflist(), '[v:val.text, v:val.valid]')))
380  call assert_equal("[['W', 1], ['E^@CCCC', 1]]", l)
381  cgetexpr ['WWWW', 'GGGG', 'ZZZZ', 'EEEE', 'CCCC', 'YYYY']
382  let l = strtrans(string(map(getqflist(), '[v:val.text, v:val.valid]')))
383  call assert_equal("[['W', 1], ['ZZZZ', 0], ['E^@CCCC', 1], ['YYYY', 0]]", l)
384  let &efm = save_efm
385endfunction
386
387" This will test for problems in quickfix:
388" A. incorrectly copying location lists which caused the location list to show
389"    a different name than the file that was actually being displayed.
390" B. not reusing the window for which the location list window is opened but
391"    instead creating new windows.
392" C. make sure that the location list window is not reused instead of the
393"    window it belongs to.
394"
395" Set up the test environment:
396function! ReadTestProtocol(name)
397  let base = substitute(a:name, '\v^test://(.*)%(\.[^.]+)?', '\1', '')
398  let word = substitute(base, '\v(.*)\..*', '\1', '')
399
400  setl modifiable
401  setl noreadonly
402  setl noswapfile
403  setl bufhidden=delete
404  %del _
405  " For problem 2:
406  " 'buftype' has to be set to reproduce the constant opening of new windows
407  setl buftype=nofile
408
409  call setline(1, word)
410
411  setl nomodified
412  setl nomodifiable
413  setl readonly
414  exe 'doautocmd BufRead ' . substitute(a:name, '\v^test://(.*)', '\1', '')
415endfunction
416
417function Test_locationlist()
418    enew
419
420    augroup testgroup
421      au!
422      autocmd BufReadCmd test://* call ReadTestProtocol(expand("<amatch>"))
423    augroup END
424
425    let words = [ "foo", "bar", "baz", "quux", "shmoo", "spam", "eggs" ]
426
427    let qflist = []
428    for word in words
429      call add(qflist, {'filename': 'test://' . word . '.txt', 'text': 'file ' . word . '.txt', })
430      " NOTE: problem 1:
431      " intentionally not setting 'lnum' so that the quickfix entries are not
432      " valid
433      call setloclist(0, qflist, ' ')
434    endfor
435
436    " Test A
437    lrewind
438    enew
439    lopen
440    lnext
441    lnext
442    lnext
443    lnext
444    vert split
445    wincmd L
446    lopen
447    wincmd p
448    lnext
449    let fileName = expand("%")
450    wincmd p
451    let locationListFileName = substitute(getline(line('.')), '\([^|]*\)|.*', '\1', '')
452    let fileName = substitute(fileName, '\\', '/', 'g')
453    let locationListFileName = substitute(locationListFileName, '\\', '/', 'g')
454    call assert_equal("test://bar.txt", fileName)
455    call assert_equal("test://bar.txt", locationListFileName)
456
457    wincmd n | only
458
459    " Test B:
460    lrewind
461    lopen
462    2
463    exe "normal \<CR>"
464    wincmd p
465    3
466    exe "normal \<CR>"
467    wincmd p
468    4
469    exe "normal \<CR>"
470    call assert_equal(2, winnr('$'))
471    wincmd n | only
472
473    " Test C:
474    lrewind
475    lopen
476    " Let's move the location list window to the top to check whether it (the
477    " first window found) will be reused when we try to open new windows:
478    wincmd K
479    2
480    exe "normal \<CR>"
481    wincmd p
482    3
483    exe "normal \<CR>"
484    wincmd p
485    4
486    exe "normal \<CR>"
487    1wincmd w
488    call assert_equal('quickfix', &buftype)
489    2wincmd w
490    let bufferName = expand("%")
491    let bufferName = substitute(bufferName, '\\', '/', 'g')
492    call assert_equal('test://quux.txt', bufferName)
493
494    wincmd n | only
495
496    augroup! testgroup
497endfunction
498
499function Test_locationlist_curwin_was_closed()
500    augroup testgroup
501      au!
502      autocmd BufReadCmd t call R(expand("<amatch>"))
503    augroup END
504
505    function R(n)
506      quit
507    endfunc
508
509    new
510    let q = []
511    call add(q, {'filename': 't' })
512    call setloclist(0, q)
513    call assert_fails('lrewind', 'E924:')
514
515    augroup! testgroup
516endfunction
517