neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

test_quickfix.vim (203884B)


      1 " Test for the quickfix feature.
      2 
      3 source check.vim
      4 source vim9.vim
      5 CheckFeature quickfix
      6 
      7 source screendump.vim
      8 
      9 set encoding=utf-8
     10 
     11 func s:setup_commands(cchar)
     12  if a:cchar == 'c'
     13    command! -nargs=* -bang Xlist <mods>clist<bang> <args>
     14    command! -nargs=* Xgetexpr <mods>cgetexpr <args>
     15    command! -nargs=* Xaddexpr <mods>caddexpr <args>
     16    command! -nargs=* -count Xolder <mods><count>colder <args>
     17    command! -nargs=* Xnewer <mods>cnewer <args>
     18    command! -nargs=* Xopen <mods> copen <args>
     19    command! -nargs=* Xwindow <mods>cwindow <args>
     20    command! -nargs=* Xbottom <mods>cbottom <args>
     21    command! -nargs=* Xclose <mods>cclose <args>
     22    command! -nargs=* -bang Xfile <mods>cfile<bang> <args>
     23    command! -nargs=* Xgetfile <mods>cgetfile <args>
     24    command! -nargs=* Xaddfile <mods>caddfile <args>
     25    command! -nargs=* -bang Xbuffer <mods>cbuffer<bang> <args>
     26    command! -nargs=* Xgetbuffer <mods>cgetbuffer <args>
     27    command! -nargs=* Xaddbuffer <mods>caddbuffer <args>
     28    command! -nargs=* Xrewind <mods>crewind <args>
     29    command! -count -nargs=* -bang Xnext <mods><count>cnext<bang> <args>
     30    command! -count -nargs=* -bang Xprev <mods><count>cprev<bang> <args>
     31    command! -nargs=* -bang Xfirst <mods>cfirst<bang> <args>
     32    command! -nargs=* -bang Xlast <mods>clast<bang> <args>
     33    command! -count -nargs=* -bang Xnfile <mods><count>cnfile<bang> <args>
     34    command! -nargs=* -bang Xpfile <mods>cpfile<bang> <args>
     35    command! -nargs=* Xexpr <mods>cexpr <args>
     36    command! -count=999 -nargs=* Xvimgrep <mods> <count>vimgrep <args>
     37    command! -nargs=* Xvimgrepadd <mods> vimgrepadd <args>
     38    command! -nargs=* Xgrep <mods> grep <args>
     39    command! -nargs=* Xgrepadd <mods> grepadd <args>
     40    command! -nargs=* Xhelpgrep helpgrep <args>
     41    command! -nargs=0 -count Xcc <count>cc
     42    command! -count=1 -nargs=0 Xbelow <mods><count>cbelow
     43    command! -count=1 -nargs=0 Xabove <mods><count>cabove
     44    command! -count=1 -nargs=0 Xbefore <mods><count>cbefore
     45    command! -count=1 -nargs=0 Xafter <mods><count>cafter
     46    command! -nargs=1 Xsethist <mods>set chistory=<args>
     47    command! -nargs=0 Xsethistdefault <mods>set chistory&
     48    let g:Xgetlist = function('getqflist')
     49    let g:Xsetlist = function('setqflist')
     50    call setqflist([], 'f')
     51  else
     52    command! -nargs=* -bang Xlist <mods>llist<bang> <args>
     53    command! -nargs=* Xgetexpr <mods>lgetexpr <args>
     54    command! -nargs=* Xaddexpr <mods>laddexpr <args>
     55    command! -nargs=* -count Xolder <mods><count>lolder <args>
     56    command! -nargs=* Xnewer <mods>lnewer <args>
     57    command! -nargs=* Xopen <mods> lopen <args>
     58    command! -nargs=* Xwindow <mods>lwindow <args>
     59    command! -nargs=* Xbottom <mods>lbottom <args>
     60    command! -nargs=* Xclose <mods>lclose <args>
     61    command! -nargs=* -bang Xfile <mods>lfile<bang> <args>
     62    command! -nargs=* Xgetfile <mods>lgetfile <args>
     63    command! -nargs=* Xaddfile <mods>laddfile <args>
     64    command! -nargs=* -bang Xbuffer <mods>lbuffer<bang> <args>
     65    command! -nargs=* Xgetbuffer <mods>lgetbuffer <args>
     66    command! -nargs=* Xaddbuffer <mods>laddbuffer <args>
     67    command! -nargs=* Xrewind <mods>lrewind <args>
     68    command! -count -nargs=* -bang Xnext <mods><count>lnext<bang> <args>
     69    command! -count -nargs=* -bang Xprev <mods><count>lprev<bang> <args>
     70    command! -nargs=* -bang Xfirst <mods>lfirst<bang> <args>
     71    command! -nargs=* -bang Xlast <mods>llast<bang> <args>
     72    command! -count -nargs=* -bang Xnfile <mods><count>lnfile<bang> <args>
     73    command! -nargs=* -bang Xpfile <mods>lpfile<bang> <args>
     74    command! -nargs=* Xexpr <mods>lexpr <args>
     75    command! -count=999 -nargs=* Xvimgrep <mods> <count>lvimgrep <args>
     76    command! -nargs=* Xvimgrepadd <mods> lvimgrepadd <args>
     77    command! -nargs=* Xgrep <mods> lgrep <args>
     78    command! -nargs=* Xgrepadd <mods> lgrepadd <args>
     79    command! -nargs=* Xhelpgrep lhelpgrep <args>
     80    command! -nargs=0 -count Xcc <count>ll
     81    command! -count=1 -nargs=0 Xbelow <mods><count>lbelow
     82    command! -count=1 -nargs=0 Xabove <mods><count>labove
     83    command! -count=1 -nargs=0 Xbefore <mods><count>lbefore
     84    command! -count=1 -nargs=0 Xafter <mods><count>lafter
     85    command! -nargs=1 Xsethist <mods>set lhistory=<args>
     86    command! -nargs=1 Xsetlocalhist <mods>setlocal lhistory=<args>
     87    command! -nargs=0 Xsethistdefault <mods>set lhistory&
     88    let g:Xgetlist = function('getloclist', [0])
     89    let g:Xsetlist = function('setloclist', [0])
     90    call setloclist(0, [], 'f')
     91  endif
     92 endfunc
     93 
     94 " This must be run before any error lists are created.
     95 func Test_AA_cc_no_errors()
     96  call assert_fails('cc', 'E42:')
     97  call assert_fails('ll', 'E42:')
     98 endfunc
     99 
    100 " Tests for the :clist and :llist commands
    101 func XlistTests(cchar)
    102  call s:setup_commands(a:cchar)
    103 
    104  if a:cchar == 'l'
    105      call assert_fails('llist', 'E776:')
    106  endif
    107  " With an empty list, command should return error
    108  Xgetexpr []
    109  silent! Xlist
    110  call assert_true(v:errmsg ==# 'E42: No Errors')
    111 
    112  " Populate the list and then try
    113  let lines =<< trim END
    114    non-error 1
    115    Xtestfile1:1:3:Line1
    116    non-error 2
    117    Xtestfile2:2:2:Line2
    118    non-error| 3
    119    Xtestfile3:3:1:Line3
    120  END
    121  Xgetexpr lines
    122 
    123  " List only valid entries
    124  let l = split(execute('Xlist', ''), "\n")
    125  call assert_equal([' 2 Xtestfile1:1 col 3: Line1',
    126 	   \ ' 4 Xtestfile2:2 col 2: Line2',
    127 	   \ ' 6 Xtestfile3:3 col 1: Line3'], l)
    128 
    129  " List all the entries
    130  let l = split(execute('Xlist!', ''), "\n")
    131  call assert_equal([' 1: non-error 1', ' 2 Xtestfile1:1 col 3: Line1',
    132 	   \ ' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2',
    133 	   \ ' 5: non-error| 3', ' 6 Xtestfile3:3 col 1: Line3'], l)
    134 
    135  " List a range of errors
    136  let l = split(execute('Xlist 3,6', ''), "\n")
    137  call assert_equal([' 4 Xtestfile2:2 col 2: Line2',
    138 	   \ ' 6 Xtestfile3:3 col 1: Line3'], l)
    139 
    140  let l = split(execute('Xlist! 3,4', ''), "\n")
    141  call assert_equal([' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2'], l)
    142 
    143  let l = split(execute('Xlist -6,-4', ''), "\n")
    144  call assert_equal([' 2 Xtestfile1:1 col 3: Line1'], l)
    145 
    146  let l = split(execute('Xlist! -5,-3', ''), "\n")
    147  call assert_equal([' 2 Xtestfile1:1 col 3: Line1',
    148 	   \ ' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2'], l)
    149 
    150  " Test for '+'
    151  let l = split(execute('Xlist! +2', ''), "\n")
    152  call assert_equal([' 2 Xtestfile1:1 col 3: Line1',
    153 	   \ ' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2'], l)
    154 
    155  " Ranged entries
    156  call g:Xsetlist([{'lnum':10,'text':'Line1'},
    157       \ {'lnum':20,'col':10,'text':'Line2'},
    158       \ {'lnum':30,'col':15,'end_col':20,'text':'Line3'},
    159       \ {'lnum':40,'end_lnum':45,'text':'Line4'},
    160       \ {'lnum':50,'end_lnum':55,'col':15,'text':'Line5'},
    161       \ {'lnum':60,'end_lnum':65,'col':25,'end_col':35,'text':'Line6'}])
    162  let l = split(execute('Xlist', ""), "\n")
    163  call assert_equal([' 1:10: Line1',
    164       \ ' 2:20 col 10: Line2',
    165       \ ' 3:30 col 15-20: Line3',
    166       \ ' 4:40-45: Line4',
    167       \ ' 5:50-55 col 15: Line5',
    168       \ ' 6:60-65 col 25-35: Line6'], l)
    169 
    170  " Different types of errors
    171  call g:Xsetlist([{'lnum':10,'col':5,'type':'W', 'text':'Warning','nr':11},
    172       \ {'lnum':20,'col':10,'type':'e','text':'Error','nr':22},
    173       \ {'lnum':30,'col':15,'type':'i','text':'Info','nr':33},
    174       \ {'lnum':40,'col':20,'type':'x', 'text':'Other','nr':44},
    175       \ {'lnum':50,'col':25,'type':"\<C-A>",'text':'one','nr':55},
    176       \ {'lnum':0,'type':'e','text':'Check type field is output even when lnum==0. ("error" was not output by v9.0.0736.)','nr':66}])
    177  let l = split(execute('Xlist', ""), "\n")
    178  call assert_equal([' 1:10 col 5 warning  11: Warning',
    179       \ ' 2:20 col 10 error  22: Error',
    180       \ ' 3:30 col 15 info  33: Info',
    181       \ ' 4:40 col 20 x  44: Other',
    182       \ ' 5:50 col 25  55: one',
    183              \ ' 6 error  66: Check type field is output even when lnum==0. ("error" was not output by v9.0.0736.)'], l)
    184 
    185  " Test for module names, one needs to explicitly set `'valid':v:true` so
    186  call g:Xsetlist([
    187 \ {'lnum':10,'col':5,'type':'W','module':'Data.Text','text':'ModuleWarning','nr':11,'valid':v:true},
    188 \ {'lnum':20,'col':10,'type':'W','module':'Data.Text','filename':'Data/Text.hs','text':'ModuleWarning','nr':22,'valid':v:true},
    189 \ {'lnum':30,'col':15,'type':'W','filename':'Data/Text.hs','text':'FileWarning','nr':33,'valid':v:true}])
    190  let l = split(execute('Xlist', ""), "\n")
    191  call assert_equal([' 1 Data.Text:10 col 5 warning  11: ModuleWarning',
    192 \ ' 2 Data.Text:20 col 10 warning  22: ModuleWarning',
    193 \ ' 3 Data/Text.hs:30 col 15 warning  33: FileWarning'], l)
    194 
    195  " Very long line should be displayed.
    196  let text = 'Line' .. repeat('1234567890', 130)
    197  let lines = ['Xtestfile9:2:9:' .. text]
    198  Xgetexpr lines
    199 
    200  let l = split(execute('Xlist', ''), "\n")
    201  call assert_equal([' 1 Xtestfile9:2 col 9: ' .. text] , l)
    202 
    203  " For help entries in the quickfix list, only the filename without directory
    204  " should be displayed
    205  Xhelpgrep setqflist()
    206  let l = split(execute('Xlist 1', ''), "\n")
    207  call assert_match('^ 1 [^\\/]\{-}:', l[0])
    208 
    209  " Error cases
    210  call assert_fails('Xlist abc', 'E488:')
    211 endfunc
    212 
    213 func Test_clist()
    214  call XlistTests('c')
    215  call XlistTests('l')
    216 endfunc
    217 
    218 " Tests for the :colder, :cnewer, :lolder and :lnewer commands
    219 " Note that this test assumes that a quickfix/location list is
    220 " already set by the caller.
    221 func XageTests(cchar)
    222  call s:setup_commands(a:cchar)
    223 
    224  if a:cchar == 'l'
    225    " No location list for the current window
    226    call assert_fails('lolder', 'E776:')
    227    call assert_fails('lnewer', 'E776:')
    228  endif
    229 
    230  let list = [{'bufnr': bufnr('%'), 'lnum': 1}]
    231  call g:Xsetlist(list)
    232 
    233  " Jumping to a non existent list should return error
    234  silent! Xolder 99
    235  call assert_true(v:errmsg ==# 'E380: At bottom of quickfix stack')
    236 
    237  silent! Xnewer 99
    238  call assert_true(v:errmsg ==# 'E381: At top of quickfix stack')
    239 
    240  " Add three quickfix/location lists
    241  Xgetexpr ['Xtestfile1:1:3:Line1']
    242  Xgetexpr ['Xtestfile2:2:2:Line2']
    243  Xgetexpr ['Xtestfile3:3:1:Line3']
    244 
    245  " Go back two lists
    246  Xolder
    247  let l = g:Xgetlist()
    248  call assert_equal('Line2', l[0].text)
    249 
    250  " Go forward two lists
    251  Xnewer
    252  let l = g:Xgetlist()
    253  call assert_equal('Line3', l[0].text)
    254 
    255  " Test for the optional count argument
    256  Xolder 2
    257  let l = g:Xgetlist()
    258  call assert_equal('Line1', l[0].text)
    259 
    260  Xnewer 2
    261  let l = g:Xgetlist()
    262  call assert_equal('Line3', l[0].text)
    263 endfunc
    264 
    265 func Test_cage()
    266  call XageTests('c')
    267  call XageTests('l')
    268 endfunc
    269 
    270 " Tests for the :cwindow, :lwindow :cclose, :lclose, :copen and :lopen
    271 " commands
    272 func XwindowTests(cchar)
    273  call s:setup_commands(a:cchar)
    274 
    275  " Opening the location list window without any errors should fail
    276  if a:cchar == 'l'
    277      call assert_fails('lopen', 'E776:')
    278      call assert_fails('lwindow', 'E776:')
    279  endif
    280 
    281  " Create a list with no valid entries
    282  Xgetexpr ['non-error 1', 'non-error 2', 'non-error 3']
    283 
    284  " Quickfix/Location window should not open with no valid errors
    285  Xwindow
    286  call assert_true(winnr('$') == 1)
    287 
    288  " Create a list with valid entries
    289  let lines =<< trim END
    290    Xtestfile1:1:3:Line1
    291    Xtestfile2:2:2:Line2
    292    Xtestfile3:3:1:Line3
    293  END
    294  Xgetexpr lines
    295 
    296  " Open the window
    297  Xwindow
    298  call assert_true(winnr('$') == 2 && winnr() == 2 &&
    299 \ getline('.') ==# 'Xtestfile1|1 col 3| Line1')
    300  redraw!
    301 
    302  " Close the window
    303  Xclose
    304  call assert_true(winnr('$') == 1)
    305 
    306  " Create a list with no valid entries
    307  Xgetexpr ['non-error 1', 'non-error 2', 'non-error 3']
    308 
    309  " Open the window
    310  Xopen 5
    311  call assert_true(winnr('$') == 2 && getline('.') ==# '|| non-error 1'
    312 	      \  && winheight(0) == 5)
    313 
    314  " Opening the window again, should move the cursor to that window
    315  wincmd t
    316  Xopen 7
    317  call assert_true(winnr('$') == 2 && winnr() == 2 &&
    318 \ winheight(0) == 7 &&
    319 \ getline('.') ==# '|| non-error 1')
    320 
    321  " :cnext in quickfix window should move to the next entry
    322  Xnext
    323  call assert_equal(2, g:Xgetlist({'idx' : 0}).idx)
    324 
    325  " Calling cwindow should close the quickfix window with no valid errors
    326  Xwindow
    327  call assert_true(winnr('$') == 1)
    328 
    329  " Specifying the width should adjust the width for a vertically split
    330  " quickfix window.
    331  vert Xopen
    332  call assert_equal(10, winwidth(0))
    333  vert Xopen 12
    334  call assert_equal(12, winwidth(0))
    335  Xclose
    336 
    337  " Horizontally or vertically splitting the quickfix window should create a
    338  " normal window/buffer
    339  Xopen
    340  wincmd s
    341  call assert_equal(0, getwininfo(win_getid())[0].quickfix)
    342  call assert_equal(0, getwininfo(win_getid())[0].loclist)
    343  call assert_notequal('quickfix', &buftype)
    344  close
    345  Xopen
    346  wincmd v
    347  call assert_equal(0, getwininfo(win_getid())[0].quickfix)
    348  call assert_equal(0, getwininfo(win_getid())[0].loclist)
    349  call assert_notequal('quickfix', &buftype)
    350  close
    351  Xopen
    352  Xclose
    353 
    354  if a:cchar == 'c'
    355      " Opening the quickfix window in multiple tab pages should reuse the
    356      " quickfix buffer
    357      let lines =<< trim END
    358        Xtestfile1:1:3:Line1
    359        Xtestfile2:2:2:Line2
    360        Xtestfile3:3:1:Line3
    361      END
    362      Xgetexpr lines
    363      Xopen
    364      let qfbufnum = bufnr('%')
    365      tabnew
    366      Xopen
    367      call assert_equal(qfbufnum, bufnr('%'))
    368      new | only | tabonly
    369  endif
    370 endfunc
    371 
    372 func Test_cwindow()
    373  call XwindowTests('c')
    374  call XwindowTests('l')
    375 endfunc
    376 
    377 func Test_copenHeight()
    378  copen
    379  wincmd H
    380  let height = winheight(0)
    381  copen 10
    382  call assert_equal(height, winheight(0))
    383  quit
    384 endfunc
    385 
    386 func Test_copenHeight_tabline()
    387  set tabline=foo showtabline=2
    388  copen
    389  wincmd H
    390  let height = winheight(0)
    391  copen 10
    392  call assert_equal(height, winheight(0))
    393  quit
    394  set tabline& showtabline&
    395 endfunc
    396 
    397 " Tests for the :cfile, :lfile, :caddfile, :laddfile, :cgetfile and :lgetfile
    398 " commands.
    399 func XfileTests(cchar)
    400  call s:setup_commands(a:cchar)
    401 
    402  let lines =<< trim END
    403    Xtestfile1:700:10:Line 700
    404    Xtestfile2:800:15:Line 800
    405  END
    406  call writefile(lines, 'Xqftestfile1')
    407 
    408  enew!
    409  Xfile Xqftestfile1
    410  let l = g:Xgetlist()
    411  call assert_true(len(l) == 2 &&
    412 \ l[0].lnum == 700 && l[0].col == 10 && l[0].text ==# 'Line 700' &&
    413 \ l[1].lnum == 800 && l[1].col == 15 && l[1].text ==# 'Line 800')
    414 
    415  " Test with a non existent file
    416  call assert_fails('Xfile non_existent_file', 'E40')
    417 
    418  " Run cfile/lfile from a modified buffer
    419  enew!
    420  silent! put ='Quickfix'
    421  silent! Xfile Xqftestfile1
    422  call assert_true(v:errmsg ==# 'E37: No write since last change (add ! to override)')
    423 
    424  call writefile(['Xtestfile3:900:30:Line 900'], 'Xqftestfile1')
    425  Xaddfile Xqftestfile1
    426  let l = g:Xgetlist()
    427  call assert_true(len(l) == 3 &&
    428 \ l[2].lnum == 900 && l[2].col == 30 && l[2].text ==# 'Line 900')
    429 
    430  let lines =<< trim END
    431    Xtestfile1:222:77:Line 222
    432    Xtestfile2:333:88:Line 333
    433  END
    434  call writefile(lines, 'Xqftestfile1')
    435 
    436  enew!
    437  Xgetfile Xqftestfile1
    438  let l = g:Xgetlist()
    439  call assert_true(len(l) == 2 &&
    440 \ l[0].lnum == 222 && l[0].col == 77 && l[0].text ==# 'Line 222' &&
    441 \ l[1].lnum == 333 && l[1].col == 88 && l[1].text ==# 'Line 333')
    442 
    443  " Test for a file with a long line and without a newline at the end
    444  let text = repeat('x', 1024)
    445  let t = 'a.txt:18:' . text
    446  call writefile([t], 'Xqftestfile1', 'b')
    447  silent! Xfile Xqftestfile1
    448  call assert_equal(text, g:Xgetlist()[0].text)
    449 
    450  call delete('Xqftestfile1')
    451 endfunc
    452 
    453 func Test_cfile()
    454  call XfileTests('c')
    455  call XfileTests('l')
    456 endfunc
    457 
    458 " Tests for the :cbuffer, :lbuffer, :caddbuffer, :laddbuffer, :cgetbuffer and
    459 " :lgetbuffer commands.
    460 func XbufferTests(cchar)
    461  call s:setup_commands(a:cchar)
    462 
    463  enew!
    464  let lines =<< trim END
    465    Xtestfile7:700:10:Line 700
    466    Xtestfile8:800:15:Line 800
    467  END
    468  silent! call setline(1, lines)
    469  Xbuffer!
    470  let l = g:Xgetlist()
    471  call assert_true(len(l) == 2 &&
    472 \ l[0].lnum == 700 && l[0].col == 10 && l[0].text ==# 'Line 700' &&
    473 \ l[1].lnum == 800 && l[1].col == 15 && l[1].text ==# 'Line 800')
    474 
    475  enew!
    476  let lines =<< trim END
    477    Xtestfile9:900:55:Line 900
    478    Xtestfile10:950:66:Line 950
    479  END
    480  silent! call setline(1, lines)
    481  Xgetbuffer
    482  let l = g:Xgetlist()
    483  call assert_true(len(l) == 2 &&
    484 \ l[0].lnum == 900 && l[0].col == 55 && l[0].text ==# 'Line 900' &&
    485 \ l[1].lnum == 950 && l[1].col == 66 && l[1].text ==# 'Line 950')
    486 
    487  enew!
    488  let lines =<< trim END
    489    Xtestfile11:700:20:Line 700
    490    Xtestfile12:750:25:Line 750
    491  END
    492  silent! call setline(1, lines)
    493  Xaddbuffer
    494  let l = g:Xgetlist()
    495  call assert_true(len(l) == 4 &&
    496 \ l[1].lnum == 950 && l[1].col == 66 && l[1].text ==# 'Line 950' &&
    497 \ l[2].lnum == 700 && l[2].col == 20 && l[2].text ==# 'Line 700' &&
    498 \ l[3].lnum == 750 && l[3].col == 25 && l[3].text ==# 'Line 750')
    499  enew!
    500 
    501  " Check for invalid buffer
    502  call assert_fails('Xbuffer 199', 'E474:')
    503 
    504  " Check for unloaded buffer
    505  edit Xtestfile1
    506  let bnr = bufnr('%')
    507  enew!
    508  call assert_fails('Xbuffer ' . bnr, 'E681:')
    509 
    510  " Check for invalid range
    511  " Using Xbuffer will not run the range check in the cbuffer/lbuffer
    512  " commands. So directly call the commands.
    513  if (a:cchar == 'c')
    514      call assert_fails('900,999cbuffer', 'E16:')
    515  else
    516      call assert_fails('900,999lbuffer', 'E16:')
    517  endif
    518 endfunc
    519 
    520 func Test_cbuffer()
    521  call XbufferTests('c')
    522  call XbufferTests('l')
    523 endfunc
    524 
    525 func XexprTests(cchar)
    526  call s:setup_commands(a:cchar)
    527 
    528  call assert_fails('Xexpr 10', 'E777:')
    529 endfunc
    530 
    531 func Test_cexpr()
    532  call XexprTests('c')
    533  call XexprTests('l')
    534 endfunc
    535 
    536 " Tests for :cnext, :cprev, :cfirst, :clast commands
    537 func Xtest_browse(cchar)
    538  call s:setup_commands(a:cchar)
    539 
    540  call g:Xsetlist([], 'f')
    541  " Jumping to first or next location list entry without any error should
    542  " result in failure
    543  if a:cchar == 'c'
    544    let err = 'E42:'
    545    let cmd = '$cc'
    546  else
    547    let err = 'E776:'
    548    let cmd = '$ll'
    549  endif
    550  call assert_fails('Xnext', err)
    551  call assert_fails('Xprev', err)
    552  call assert_fails('Xnfile', err)
    553  call assert_fails('Xpfile', err)
    554  call assert_fails(cmd, err)
    555 
    556  Xexpr ''
    557  call assert_fails(cmd, 'E42:')
    558 
    559  call s:create_test_file('Xqftestfile1')
    560  call s:create_test_file('Xqftestfile2')
    561 
    562  let lines =<< trim END
    563    Xqftestfile1:5:Line5
    564    Xqftestfile1:6:Line6
    565    Xqftestfile2:10:Line10
    566    Xqftestfile2:11:Line11
    567    RegularLine1
    568    RegularLine2
    569  END
    570  Xgetexpr lines
    571 
    572  Xfirst
    573  call assert_fails('-5Xcc', 'E16:')
    574  call assert_fails('Xprev', 'E553')
    575  call assert_fails('Xpfile', 'E553')
    576  Xnfile
    577  call assert_equal('Xqftestfile2', @%)
    578  call assert_equal(10, line('.'))
    579  Xpfile
    580  call assert_equal('Xqftestfile1', @%)
    581  call assert_equal(6, line('.'))
    582  5Xcc
    583  call assert_equal(5, g:Xgetlist({'idx':0}).idx)
    584  2Xcc
    585  call assert_equal(2, g:Xgetlist({'idx':0}).idx)
    586  if a:cchar == 'c'
    587    cc
    588  else
    589    ll
    590  endif
    591  call assert_equal(2, g:Xgetlist({'idx':0}).idx)
    592  10Xcc
    593  call assert_equal(6, g:Xgetlist({'idx':0}).idx)
    594  Xlast
    595  Xprev
    596  call assert_equal('Xqftestfile2', @%)
    597  call assert_equal(11, line('.'))
    598  call assert_fails('Xnext', 'E553')
    599  call assert_fails('Xnfile', 'E553')
    600  " To process the range using quickfix list entries, directly use the
    601  " quickfix commands (don't use the user defined commands)
    602  if a:cchar == 'c'
    603    $cc
    604  else
    605    $ll
    606  endif
    607  call assert_equal(6, g:Xgetlist({'idx':0}).idx)
    608  Xrewind
    609  call assert_equal('Xqftestfile1', @%)
    610  call assert_equal(5, line('.'))
    611 
    612  10Xnext
    613  call assert_equal('Xqftestfile2', @%)
    614  call assert_equal(11, line('.'))
    615  10Xprev
    616  call assert_equal('Xqftestfile1', @%)
    617  call assert_equal(5, line('.'))
    618 
    619  " Jumping to an error from the error window using cc command
    620  let lines =<< trim END
    621    Xqftestfile1:5:Line5
    622    Xqftestfile1:6:Line6
    623    Xqftestfile2:10:Line10
    624    Xqftestfile2:11:Line11
    625  END
    626  Xgetexpr lines
    627  Xopen
    628  10Xcc
    629  call assert_equal(11, line('.'))
    630  call assert_equal('Xqftestfile2', @%)
    631  Xopen
    632  call cursor(2, 1)
    633  if a:cchar == 'c'
    634    .cc
    635  else
    636    .ll
    637  endif
    638  call assert_equal(6, line('.'))
    639  call assert_equal('Xqftestfile1', @%)
    640 
    641  " Jumping to an error from the error window (when only the error window is
    642  " present)
    643  Xopen | only
    644  Xlast 1
    645  call assert_equal(5, line('.'))
    646  call assert_equal('Xqftestfile1', @%)
    647 
    648  Xexpr ""
    649  call assert_fails('Xnext', 'E42:')
    650 
    651  call delete('Xqftestfile1')
    652  call delete('Xqftestfile2')
    653 
    654  " Should be able to use next/prev with invalid entries
    655  Xexpr ""
    656  call assert_equal(0, g:Xgetlist({'idx' : 0}).idx)
    657  call assert_equal(0, g:Xgetlist({'size' : 0}).size)
    658  Xaddexpr ['foo', 'bar', 'baz', 'quux', 'sh|moo']
    659  call assert_equal(5, g:Xgetlist({'size' : 0}).size)
    660  Xlast
    661  call assert_equal(5, g:Xgetlist({'idx' : 0}).idx)
    662  Xfirst
    663  call assert_equal(1, g:Xgetlist({'idx' : 0}).idx)
    664  2Xnext
    665  call assert_equal(3, g:Xgetlist({'idx' : 0}).idx)
    666 endfunc
    667 
    668 func Test_browse()
    669  call Xtest_browse('c')
    670  call Xtest_browse('l')
    671 endfunc
    672 
    673 " Test for memory allocation failures
    674 func Xnomem_tests(cchar)
    675  call s:setup_commands(a:cchar)
    676 
    677  call test_alloc_fail(GetAllocId('qf_dirname_start'), 0, 0)
    678  call assert_fails('Xvimgrep vim runtest.vim', 'E342:')
    679 
    680  call test_alloc_fail(GetAllocId('qf_dirname_now'), 0, 0)
    681  call assert_fails('Xvimgrep vim runtest.vim', 'E342:')
    682 
    683  call test_alloc_fail(GetAllocId('qf_namebuf'), 0, 0)
    684  call assert_fails('Xfile runtest.vim', 'E342:')
    685 
    686  call test_alloc_fail(GetAllocId('qf_errmsg'), 0, 0)
    687  call assert_fails('Xfile runtest.vim', 'E342:')
    688 
    689  call test_alloc_fail(GetAllocId('qf_pattern'), 0, 0)
    690  call assert_fails('Xfile runtest.vim', 'E342:')
    691 
    692  call test_alloc_fail(GetAllocId('qf_efm_fmtstr'), 0, 0)
    693  set efm=%f
    694  call assert_fails('Xexpr ["Xfile1"]', 'E342:')
    695  set efm&
    696 
    697  call test_alloc_fail(GetAllocId('qf_efm_fmtpart'), 0, 0)
    698  set efm=%f:%l:%m,%f-%l-%m
    699  call assert_fails('Xaddexpr ["Xfile2", "Xfile3"]', 'E342:')
    700  set efm&
    701 
    702  call test_alloc_fail(GetAllocId('qf_title'), 0, 0)
    703  call assert_fails('Xexpr ""', 'E342:')
    704  call assert_equal('', g:Xgetlist({'all': 1}).title)
    705 
    706  call test_alloc_fail(GetAllocId('qf_mef_name'), 0, 0)
    707  set makeef=Xtmp##.err
    708  call assert_fails('Xgrep needle haystack', 'E342:')
    709  set makeef&
    710 
    711  call test_alloc_fail(GetAllocId('qf_qfline'), 0, 0)
    712  call assert_fails('Xexpr "Xfile1:10:Line10"', 'E342:')
    713 
    714  if a:cchar == 'l'
    715    for id in ['qf_qfline', 'qf_qfinfo']
    716      lgetexpr ["Xfile1:10:L10", "Xfile2:20:L20"]
    717      call test_alloc_fail(GetAllocId(id), 0, 0)
    718      call assert_fails('new', 'E342:')
    719      call assert_equal(2, winnr('$'))
    720      call assert_equal([], getloclist(0))
    721      %bw!
    722    endfor
    723  endif
    724 
    725  call test_alloc_fail(GetAllocId('qf_qfline'), 0, 0)
    726  try
    727    call assert_fails('Xvimgrep vim runtest.vim', 'E342:')
    728  catch /^Vim:Interrupt$/
    729  endtry
    730 
    731  call test_alloc_fail(GetAllocId('qf_qfline'), 0, 0)
    732  try
    733    call assert_fails('Xvimgrep /vim/f runtest.vim', 'E342:')
    734  catch /^Vim:Interrupt$/
    735  endtry
    736 
    737  let l = getqflist({"lines": ["Xfile1:10:L10"]})
    738  call test_alloc_fail(GetAllocId('qf_qfline'), 0, 0)
    739  call assert_fails('call g:Xsetlist(l.items)', 'E342:')
    740 
    741  call test_alloc_fail(GetAllocId('qf_qfline'), 0, 0)
    742  try
    743    call assert_fails('Xhelpgrep quickfix', 'E342:')
    744  catch /^Vim:Interrupt$/
    745  endtry
    746 
    747  call test_alloc_fail(GetAllocId('qf_qfinfo'), 0, 0)
    748  call assert_fails('let l = g:Xgetlist({"lines": ["Xfile1:10:L10"]})', 'E342:')
    749  call assert_equal(#{items: []}, l)
    750 
    751  if a:cchar == 'l'
    752    call setqflist([], 'f')
    753    call setloclist(0, [], 'f')
    754    call test_alloc_fail(GetAllocId('qf_qfinfo'), 0, 0)
    755    call assert_fails('lhelpgrep quickfix', 'E342:')
    756    call assert_equal([], getloclist(0))
    757 
    758    call test_alloc_fail(GetAllocId('qf_qfinfo'), 0, 0)
    759    call assert_fails('lvimgrep vim runtest.vim', 'E342:')
    760 
    761    let l = getqflist({"lines": ["Xfile1:10:L10"]})
    762    call test_alloc_fail(GetAllocId('qf_qfinfo'), 0, 0)
    763    call assert_fails('call setloclist(0, l.items)', 'E342:')
    764 
    765    call test_alloc_fail(GetAllocId('qf_qfinfo'), 0, 0)
    766    call assert_fails('lbuffer', 'E342:')
    767 
    768    call test_alloc_fail(GetAllocId('qf_qfinfo'), 0, 0)
    769    call assert_fails('lexpr ["Xfile1:10:L10", "Xfile2:20:L20"]', 'E342:')
    770 
    771    call test_alloc_fail(GetAllocId('qf_qfinfo'), 0, 0)
    772    call assert_fails('lfile runtest.vim', 'E342:')
    773  endif
    774 
    775  call test_alloc_fail(GetAllocId('qf_dirstack'), 0, 0)
    776  set efm=%DEntering\ dir\ %f,%f:%l:%m
    777  call assert_fails('Xexpr ["Entering dir abc", "abc.txt:1:Hello world"]', 'E342:')
    778  set efm&
    779 
    780  call test_alloc_fail(GetAllocId('qf_dirstack'), 0, 0)
    781  set efm=%+P[%f],(%l)%m
    782  call assert_fails('Xexpr ["[runtest.vim]", "(1)Hello"]', 'E342:')
    783  set efm&
    784 
    785  call test_alloc_fail(GetAllocId('qf_multiline_pfx'), 0, 0)
    786  set efm=%EError,%Cline\ %l,%Z%m
    787  call assert_fails('Xexpr ["Error", "line 1", "msg"]', 'E342:')
    788  set efm&
    789 
    790  call test_alloc_fail(GetAllocId('qf_makecmd'), 0, 0)
    791  call assert_fails('Xgrep vim runtest.vim', 'E342:')
    792 
    793  call test_alloc_fail(GetAllocId('qf_linebuf'), 0, 0)
    794  call assert_fails('Xexpr repeat("a", 8192)', 'E342:')
    795 
    796  call test_alloc_fail(GetAllocId('qf_linebuf'), 0, 0)
    797  call assert_fails('Xexpr [repeat("a", 8192)]', 'E342:')
    798 
    799  new
    800  call setline(1, repeat('a', 8192))
    801  call test_alloc_fail(GetAllocId('qf_linebuf'), 0, 0)
    802  call assert_fails('Xbuffer', 'E342:')
    803  %bw!
    804 
    805  call writefile([repeat('a', 8192)], 'Xtest')
    806  call test_alloc_fail(GetAllocId('qf_linebuf'), 0, 0)
    807  call assert_fails('Xfile Xtest', 'E342:')
    808  call delete('Xtest')
    809 endfunc
    810 
    811 func Test_nomem()
    812  throw 'Skipped: Nvim does not support test_alloc_fail()'
    813  call Xnomem_tests('c')
    814  call Xnomem_tests('l')
    815 endfunc
    816 
    817 func s:test_xhelpgrep(cchar)
    818  call s:setup_commands(a:cchar)
    819  Xhelpgrep quickfix
    820  Xopen
    821  if a:cchar == 'c'
    822    let title_text = ':helpgrep quickfix'
    823  else
    824    let title_text = ':lhelpgrep quickfix'
    825  endif
    826  call assert_true(w:quickfix_title =~ title_text, w:quickfix_title)
    827 
    828  " Jumping to a help topic should open the help window
    829  only
    830  Xnext
    831  call assert_true(&buftype == 'help')
    832  call assert_true(winnr('$') == 2)
    833  " Jumping to the next match should reuse the help window
    834  Xnext
    835  call assert_true(&buftype == 'help')
    836  call assert_true(winnr() == 1)
    837  call assert_true(winnr('$') == 2)
    838  " Jumping to the next match from the quickfix window should reuse the help
    839  " window
    840  Xopen
    841  Xnext
    842  call assert_true(&buftype == 'help')
    843  call assert_true(winnr() == 1)
    844  call assert_true(winnr('$') == 2)
    845  call assert_match('|\d\+ col \d\+-\d\+|', getbufline(winbufnr(2), 1)[0])
    846 
    847  " This wipes out the buffer, make sure that doesn't cause trouble.
    848  Xclose
    849 
    850  " When the current window is vertically split, jumping to a help match
    851  " should open the help window at the top.
    852  only | enew
    853  let w1 = win_getid()
    854  vert new
    855  let w2 = win_getid()
    856  Xnext
    857  let w3 = win_getid()
    858  call assert_true(&buftype == 'help')
    859  call assert_true(winnr() == 1)
    860  " See jump_to_help_window() for details
    861  let w2_width = winwidth(w2)
    862  if w2_width != &columns && w2_width < 80
    863    call assert_equal(['col', [['leaf', w3],
    864          \ ['row', [['leaf', w2], ['leaf', w1]]]]], winlayout())
    865  else
    866    call assert_equal(['row', [['col', [['leaf', w3], ['leaf', w2]]],
    867          \ ['leaf', w1]]] , winlayout())
    868  endif
    869 
    870  new | only
    871  set buftype=help
    872  set modified
    873  call assert_fails('Xnext', 'E37:')
    874  set nomodified
    875  new | only
    876 
    877  if a:cchar == 'l'
    878      " When a help window is present, running :lhelpgrep should reuse the
    879      " help window and not the current window
    880      new | only
    881      call g:Xsetlist([], 'f')
    882      help index.txt
    883      wincmd w
    884      lhelpgrep quickfix
    885      call assert_equal(1, winnr())
    886      call assert_notequal([], getloclist(1))
    887      call assert_equal([], getloclist(2))
    888  endif
    889 
    890  new | only
    891 
    892  " Search for non existing help string
    893  call assert_fails('Xhelpgrep a1b2c3', 'E480:')
    894  " Invalid regular expression
    895  call assert_fails('Xhelpgrep \@<!', 'E866:')
    896 endfunc
    897 
    898 func Test_helpgrep()
    899  call s:test_xhelpgrep('c')
    900  helpclose
    901  call s:test_xhelpgrep('l')
    902 endfunc
    903 
    904 " When running the :helpgrep command, if an autocmd modifies the 'cpoptions'
    905 " value, then Vim crashes. (issue fixed by 7.2b-004 and 8.2.4453)
    906 func Test_helpgrep_restore_cpo_aucmd()
    907  let save_cpo = &cpo
    908  augroup QF_Test
    909    au!
    910    autocmd BufNew * set cpo=acd
    911  augroup END
    912 
    913  helpgrep quickfix
    914  call assert_equal('acd', &cpo)
    915  %bw!
    916 
    917  set cpo&vim
    918  augroup QF_Test
    919    au!
    920    autocmd BufReadPost * set cpo=
    921  augroup END
    922 
    923  helpgrep buffer
    924  call assert_equal('', &cpo)
    925 
    926  augroup QF_Test
    927    au!
    928  augroup END
    929  %bw!
    930  let &cpo = save_cpo
    931 endfunc
    932 
    933 func Test_errortitle()
    934  augroup QfBufWinEnter
    935    au!
    936    au BufWinEnter * :let g:a=get(w:, 'quickfix_title', 'NONE')
    937  augroup END
    938  copen
    939  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'')'}]
    940  call setqflist(a)
    941  call assert_equal(':setqflist()', g:a)
    942  augroup QfBufWinEnter
    943    au!
    944  augroup END
    945  augroup! QfBufWinEnter
    946 endfunc
    947 
    948 func Test_vimgreptitle()
    949  augroup QfBufWinEnter
    950    au!
    951    au BufWinEnter * :let g:a=get(w:, 'quickfix_title', 'NONE')
    952  augroup END
    953  try
    954    vimgrep /pattern/j file
    955  catch /E480/
    956  endtry
    957  copen
    958  call assert_equal(':    vimgrep /pattern/j file', g:a)
    959  augroup QfBufWinEnter
    960    au!
    961  augroup END
    962  augroup! QfBufWinEnter
    963 endfunc
    964 
    965 func Test_bufwinenter_once()
    966  augroup QfBufWinEnter
    967    au!
    968    au BufWinEnter * let g:got_afile ..= 'got ' .. expand('<afile>')
    969  augroup END
    970  let g:got_afile = ''
    971  copen
    972  call assert_equal('got quickfix', g:got_afile)
    973 
    974  cclose
    975  unlet g:got_afile
    976  augroup QfBufWinEnter
    977    au!
    978  augroup END
    979  augroup! QfBufWinEnter
    980 endfunc
    981 
    982 func XqfTitleTests(cchar)
    983  call s:setup_commands(a:cchar)
    984 
    985  Xgetexpr ['file:1:1:message']
    986  let l = g:Xgetlist()
    987  if a:cchar == 'c'
    988    call setqflist(l, 'r')
    989  else
    990    call setloclist(0, l, 'r')
    991  endif
    992 
    993  Xopen
    994  if a:cchar == 'c'
    995    let title = ':setqflist()'
    996  else
    997    let title = ':setloclist()'
    998  endif
    999  call assert_equal(title, w:quickfix_title)
   1000  Xclose
   1001 endfunc
   1002 
   1003 " Tests for quickfix window's title
   1004 func Test_qf_title()
   1005  call XqfTitleTests('c')
   1006  call XqfTitleTests('l')
   1007 endfunc
   1008 
   1009 " Tests for 'errorformat'
   1010 func Test_efm()
   1011  let save_efm = &efm
   1012  set efm=%EEEE%m,%WWWW%m,%+CCCC%.%#,%-GGGG%.%#
   1013  cgetexpr ['WWWW', 'EEEE', 'CCCC']
   1014  let l = strtrans(string(map(getqflist(), '[v:val.text, v:val.valid]')))
   1015  call assert_equal("[['W', 1], ['E^@CCCC', 1]]", l)
   1016  cgetexpr ['WWWW', 'GGGG', 'EEEE', 'CCCC']
   1017  let l = strtrans(string(map(getqflist(), '[v:val.text, v:val.valid]')))
   1018  call assert_equal("[['W', 1], ['E^@CCCC', 1]]", l)
   1019  cgetexpr ['WWWW', 'GGGG', 'ZZZZ', 'EEEE', 'CCCC', 'YYYY']
   1020  let l = strtrans(string(map(getqflist(), '[v:val.text, v:val.valid]')))
   1021  call assert_equal("[['W', 1], ['ZZZZ', 0], ['E^@CCCC', 1], ['YYYY', 0]]", l)
   1022  let &efm = save_efm
   1023 endfunc
   1024 
   1025 " This will test for problems in quickfix:
   1026 " A. incorrectly copying location lists which caused the location list to show
   1027 "    a different name than the file that was actually being displayed.
   1028 " B. not reusing the window for which the location list window is opened but
   1029 "    instead creating new windows.
   1030 " C. make sure that the location list window is not reused instead of the
   1031 "    window it belongs to.
   1032 "
   1033 " Set up the test environment:
   1034 func ReadTestProtocol(name)
   1035  let base = substitute(a:name, '\v^test://(.*)%(\.[^.]+)?', '\1', '')
   1036  let word = substitute(base, '\v(.*)\..*', '\1', '')
   1037 
   1038  setl modifiable
   1039  setl noreadonly
   1040  setl noswapfile
   1041  setl bufhidden=delete
   1042  %del _
   1043  " For problem 2:
   1044  " 'buftype' has to be set to reproduce the constant opening of new windows
   1045  setl buftype=nofile
   1046 
   1047  call setline(1, word)
   1048 
   1049  setl nomodified
   1050  setl nomodifiable
   1051  setl readonly
   1052  exe 'doautocmd BufRead ' . substitute(a:name, '\v^test://(.*)', '\1', '')
   1053 endfunc
   1054 
   1055 func Test_locationlist()
   1056  enew
   1057 
   1058  augroup testgroup
   1059    au!
   1060    autocmd BufReadCmd test://* call ReadTestProtocol(expand("<amatch>"))
   1061  augroup END
   1062 
   1063  let words = [ "foo", "bar", "baz", "quux", "shmoo", "spam", "eggs" ]
   1064 
   1065  let qflist = []
   1066  for word in words
   1067    call add(qflist, {'filename': 'test://' . word . '.txt', 'text': 'file ' . word . '.txt', })
   1068    " NOTE: problem 1:
   1069    " intentionally not setting 'lnum' so that the quickfix entries are not
   1070    " valid
   1071    eval qflist->setloclist(0, ' ')
   1072  endfor
   1073 
   1074  " Test A
   1075  lrewind
   1076  enew
   1077  lopen
   1078  4lnext
   1079  vert split
   1080  wincmd L
   1081  lopen
   1082  wincmd p
   1083  lnext
   1084  let fileName = expand("%")
   1085  wincmd p
   1086  let locationListFileName = substitute(getline(line('.')), '\([^|]*\)|.*', '\1', '')
   1087  let fileName = substitute(fileName, '\\', '/', 'g')
   1088  let locationListFileName = substitute(locationListFileName, '\\', '/', 'g')
   1089  call assert_equal("test://bar.txt", fileName)
   1090  call assert_equal("test://bar.txt", locationListFileName)
   1091 
   1092  wincmd n | only
   1093 
   1094  " Test B:
   1095  lrewind
   1096  lopen
   1097  2
   1098  exe "normal \<CR>"
   1099  wincmd p
   1100  3
   1101  exe "normal \<CR>"
   1102  wincmd p
   1103  4
   1104  exe "normal \<CR>"
   1105  call assert_equal(2, winnr('$'))
   1106  wincmd n | only
   1107 
   1108  " Test C:
   1109  lrewind
   1110  lopen
   1111  " Let's move the location list window to the top to check whether it (the
   1112  " first window found) will be reused when we try to open new windows:
   1113  wincmd K
   1114  2
   1115  exe "normal \<CR>"
   1116  wincmd p
   1117  3
   1118  exe "normal \<CR>"
   1119  wincmd p
   1120  4
   1121  exe "normal \<CR>"
   1122  1wincmd w
   1123  call assert_equal('quickfix', &buftype)
   1124  2wincmd w
   1125  let bufferName = expand("%")
   1126  let bufferName = substitute(bufferName, '\\', '/', 'g')
   1127  call assert_equal('test://quux.txt', bufferName)
   1128 
   1129  wincmd n | only
   1130 
   1131  augroup! testgroup
   1132 endfunc
   1133 
   1134 func Test_locationlist_curwin_was_closed()
   1135  augroup testgroup
   1136    au!
   1137    autocmd BufReadCmd test_curwin.txt call R(expand("<amatch>"))
   1138  augroup END
   1139 
   1140  func! R(n)
   1141    quit
   1142  endfunc
   1143 
   1144  new
   1145  let q = []
   1146  call add(q, {'filename': 'test_curwin.txt' })
   1147  call setloclist(0, q)
   1148  call assert_fails('lrewind', 'E924:')
   1149 
   1150  augroup! testgroup
   1151  delfunc R
   1152 endfunc
   1153 
   1154 func Test_locationlist_cross_tab_jump()
   1155  call writefile(['loclistfoo'], 'loclistfoo')
   1156  call writefile(['loclistbar'], 'loclistbar')
   1157  set switchbuf=usetab
   1158 
   1159  edit loclistfoo
   1160  tabedit loclistbar
   1161  silent lgrep loclistfoo loclist*
   1162  call assert_equal(1, tabpagenr())
   1163 
   1164  enew | only | tabonly
   1165  set switchbuf&vim
   1166  call delete('loclistfoo')
   1167  call delete('loclistbar')
   1168 endfunc
   1169 
   1170 " More tests for 'errorformat'
   1171 func Test_efm1()
   1172  " The 'errorformat' setting is different on non-Unix systems.
   1173  " This test works only on Unix-like systems.
   1174  CheckUnix
   1175 
   1176  let l =<< trim [DATA]
   1177    "Xtestfile", line 4.12: 1506-045 (S) Undeclared identifier fd_set.
   1178    "Xtestfile", line 6 col 19; this is an error
   1179    gcc -c -DHAVE_CONFIsing-prototypes -I/usr/X11R6/include  version.c
   1180    Xtestfile:9: parse error before `asd'
   1181    make: *** [src/vim/testdir/Makefile:100: test_quickfix] Error 1
   1182    in file "Xtestfile" linenr 10: there is an error
   1183 
   1184    2 returned
   1185    "Xtestfile", line 11 col 1; this is an error
   1186    "Xtestfile", line 12 col 2; this is another error
   1187    "Xtestfile", line 14:10; this is an error in column 10
   1188    =Xtestfile=, line 15:10; this is another error, but in vcol 10 this time
   1189    "Xtestfile", linenr 16: yet another problem
   1190    Error in "Xtestfile" at line 17:
   1191    x should be a dot
   1192 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 17
   1193                ^
   1194    Error in "Xtestfile" at line 18:
   1195    x should be a dot
   1196 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 18
   1197    .............^
   1198    Error in "Xtestfile" at line 19:
   1199    x should be a dot
   1200 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 19
   1201    --------------^
   1202    Error in "Xtestfile" at line 20:
   1203    x should be a dot
   1204 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 20
   1205        ^
   1206 
   1207    Does anyone know what is the problem and how to correction it?
   1208    "Xtestfile", line 21 col 9: What is the title of the quickfix window?
   1209    "Xtestfile", line 22 col 9: What is the title of the quickfix window?
   1210  [DATA]
   1211 
   1212  call writefile(l, 'Xerrorfile1')
   1213  call writefile(l[:-2], 'Xerrorfile2')
   1214 
   1215  let m =<< [DATA]
   1216 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  2
   1217 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  3
   1218 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  4
   1219 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  5
   1220 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  6
   1221 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  7
   1222 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  8
   1223 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line  9
   1224 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 10
   1225 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 11
   1226 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 12
   1227 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 13
   1228 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 14
   1229 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 15
   1230 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 16
   1231 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 17
   1232 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 18
   1233 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 19
   1234 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 20
   1235 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 21
   1236 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    line 22
   1237 [DATA]
   1238  call writefile(m, 'Xtestfile')
   1239 
   1240  let save_efm = &efm
   1241  set efm+==%f=\\,\ line\ %l%*\\D%v%*[^\ ]\ %m
   1242  set efm^=%AError\ in\ \"%f\"\ at\ line\ %l:,%Z%p^,%C%m
   1243 
   1244  exe 'cf Xerrorfile2'
   1245  clast
   1246  copen
   1247  call assert_equal(':cf Xerrorfile2', w:quickfix_title)
   1248  wincmd p
   1249 
   1250  exe 'cf Xerrorfile1'
   1251  call assert_equal([4, 12], [line('.'), col('.')])
   1252  cn
   1253  call assert_equal([6, 19], [line('.'), col('.')])
   1254  cn
   1255  call assert_equal([9, 2], [line('.'), col('.')])
   1256  cn
   1257  call assert_equal([10, 2], [line('.'), col('.')])
   1258  cn
   1259  call assert_equal([11, 1], [line('.'), col('.')])
   1260  cn
   1261  call assert_equal([12, 2], [line('.'), col('.')])
   1262  cn
   1263  call assert_equal([14, 10], [line('.'), col('.')])
   1264  cn
   1265  call assert_equal([15, 3, 10], [line('.'), col('.'), virtcol('.')])
   1266  cn
   1267  call assert_equal([16, 2], [line('.'), col('.')])
   1268  cn
   1269  call assert_equal([17, 6], [line('.'), col('.')])
   1270  cn
   1271  call assert_equal([18, 7], [line('.'), col('.')])
   1272  cn
   1273  call assert_equal([19, 8], [line('.'), col('.')])
   1274  cn
   1275  call assert_equal([20, 9], [line('.'), col('.')])
   1276  clast
   1277  cprev
   1278  cprev
   1279  wincmd w
   1280  call assert_equal(':cf Xerrorfile1', w:quickfix_title)
   1281  wincmd p
   1282 
   1283  let &efm = save_efm
   1284  call delete('Xerrorfile1')
   1285  call delete('Xerrorfile2')
   1286  call delete('Xtestfile')
   1287 endfunc
   1288 
   1289 " Test for quickfix directory stack support
   1290 func s:dir_stack_tests(cchar)
   1291  call s:setup_commands(a:cchar)
   1292 
   1293  let save_efm=&efm
   1294  set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f'
   1295 
   1296  let lines =<< trim END
   1297    Entering dir 'dir1/a'
   1298    habits2.txt:1:Nine Healthy Habits
   1299    Entering dir 'b'
   1300    habits3.txt:2:0 Hours of television
   1301    habits2.txt:7:5 Small meals
   1302    Entering dir 'dir1/c'
   1303    habits4.txt:3:1 Hour of exercise
   1304    Leaving dir 'dir1/c'
   1305    Leaving dir 'dir1/a'
   1306    habits1.txt:4:2 Liters of water
   1307    Entering dir 'dir2'
   1308    habits5.txt:5:3 Cups of hot green tea
   1309    Leaving dir 'dir2'
   1310  END
   1311 
   1312  Xexpr ""
   1313  for l in lines
   1314      Xaddexpr l
   1315  endfor
   1316 
   1317  let qf = g:Xgetlist()
   1318 
   1319  call assert_equal('dir1/a/habits2.txt', bufname(qf[1].bufnr))
   1320  call assert_equal(1, qf[1].lnum)
   1321  call assert_equal('dir1/a/b/habits3.txt', bufname(qf[3].bufnr))
   1322  call assert_equal(2, qf[3].lnum)
   1323  call assert_equal('dir1/a/habits2.txt', bufname(qf[4].bufnr))
   1324  call assert_equal(7, qf[4].lnum)
   1325  call assert_equal('dir1/c/habits4.txt', bufname(qf[6].bufnr))
   1326  call assert_equal(3, qf[6].lnum)
   1327  call assert_equal('habits1.txt', bufname(qf[9].bufnr))
   1328  call assert_equal(4, qf[9].lnum)
   1329  call assert_equal('dir2/habits5.txt', bufname(qf[11].bufnr))
   1330  call assert_equal(5, qf[11].lnum)
   1331 
   1332  let &efm=save_efm
   1333 endfunc
   1334 
   1335 " Tests for %D and %X errorformat options
   1336 func Test_efm_dirstack()
   1337  " Create the directory stack and files
   1338  call mkdir('dir1')
   1339  call mkdir('dir1/a')
   1340  call mkdir('dir1/a/b')
   1341  call mkdir('dir1/c')
   1342  call mkdir('dir2')
   1343 
   1344  let lines =<< trim END
   1345    Nine Healthy Habits
   1346    0 Hours of television
   1347    1 Hour of exercise
   1348    2 Liters of water
   1349    3 Cups of hot green tea
   1350    4 Short mental breaks
   1351    5 Small meals
   1352    6 AM wake up time
   1353    7 Minutes of laughter
   1354    8 Hours of sleep (at least)
   1355    9 PM end of the day and off to bed
   1356  END
   1357  call writefile(lines, 'habits1.txt')
   1358  call writefile(lines, 'dir1/a/habits2.txt')
   1359  call writefile(lines, 'dir1/a/b/habits3.txt')
   1360  call writefile(lines, 'dir1/c/habits4.txt')
   1361  call writefile(lines, 'dir2/habits5.txt')
   1362 
   1363  call s:dir_stack_tests('c')
   1364  call s:dir_stack_tests('l')
   1365 
   1366  call delete('dir1', 'rf')
   1367  call delete('dir2', 'rf')
   1368  call delete('habits1.txt')
   1369 endfunc
   1370 
   1371 " Test for resync after continuing an ignored message
   1372 func Xefm_ignore_continuations(cchar)
   1373  call s:setup_commands(a:cchar)
   1374 
   1375  let save_efm = &efm
   1376 
   1377  let &efm =
   1378 \ '%Eerror %m %l,' .
   1379 \ '%-Wignored %m %l,' .
   1380 \ '%+Cmore ignored %m %l,' .
   1381 \ '%Zignored end'
   1382  let lines =<< trim END
   1383    ignored warning 1
   1384    more ignored continuation 2
   1385    ignored end
   1386    error resync 4
   1387  END
   1388  Xgetexpr lines
   1389  let l = map(g:Xgetlist(), '[v:val.text, v:val.valid, v:val.lnum, v:val.type]')
   1390  call assert_equal([['resync', 1, 4, 'E']], l)
   1391 
   1392  let &efm = save_efm
   1393 endfunc
   1394 
   1395 func Test_efm_ignore_continuations()
   1396  call Xefm_ignore_continuations('c')
   1397  call Xefm_ignore_continuations('l')
   1398 endfunc
   1399 
   1400 " Tests for invalid error format specifies
   1401 func Xinvalid_efm_Tests(cchar)
   1402  call s:setup_commands(a:cchar)
   1403 
   1404  let save_efm = &efm
   1405 
   1406  set efm=%f:%l:%m,%f:%f:%l:%m
   1407  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E372:')
   1408 
   1409  set efm=%f:%l:%m,%f:%l:%r:%m
   1410  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E373:')
   1411 
   1412  set efm=%f:%l:%m,%O:%f:%l:%m
   1413  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E373:')
   1414 
   1415  set efm=%f:%l:%m,%f:%l:%*[^a-z
   1416  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E374:')
   1417 
   1418  set efm=%f:%l:%m,%f:%l:%*c
   1419  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E375:')
   1420 
   1421  set efm=%f:%l:%m,%L%M%N
   1422  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E376:')
   1423 
   1424  set efm=%f:%l:%m,%f:%l:%m:%R
   1425  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E377:')
   1426 
   1427  " Invalid regular expression
   1428  set efm=%\\%%k
   1429  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E867:')
   1430 
   1431  set efm=
   1432  call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E378:')
   1433 
   1434  " Empty directory name. When there is an error in parsing new entries, make
   1435  " sure the previous quickfix list is made the current list.
   1436  set efm&
   1437  cexpr ["one", "two"]
   1438  let qf_id = getqflist(#{id: 0}).id
   1439  set efm=%DEntering\ dir\ abc,%f:%l:%m
   1440  call assert_fails('Xexpr ["Entering dir abc", "abc.txt:1:Hello world"]', 'E379:')
   1441  call assert_equal(qf_id, getqflist(#{id: 0}).id)
   1442 
   1443  let &efm = save_efm
   1444 endfunc
   1445 
   1446 func Test_invalid_efm()
   1447  call Xinvalid_efm_Tests('c')
   1448  call Xinvalid_efm_Tests('l')
   1449 endfunc
   1450 
   1451 " TODO:
   1452 " Add tests for the following formats in 'errorformat'
   1453 "	%r  %O
   1454 func Test_efm2()
   1455  let save_efm = &efm
   1456 
   1457  " Test for %s format in efm
   1458  set efm=%f:%s
   1459  cexpr 'Xtestfile:Line search text'
   1460  let l = getqflist()
   1461  call assert_equal('^\VLine search text\$', l[0].pattern)
   1462  call assert_equal(0, l[0].lnum)
   1463 
   1464  let l = split(execute('clist', ''), "\n")
   1465  call assert_equal([' 1 Xtestfile:^\VLine search text\$:  '], l)
   1466 
   1467  " Test for a long line
   1468  cexpr 'Xtestfile:' . repeat('a', 1026)
   1469  let l = getqflist()
   1470  call assert_equal('^\V' . repeat('a', 1019) . '\$', l[0].pattern)
   1471 
   1472  " Test for %P, %Q and %t format specifiers
   1473  let lines =<< trim [DATA]
   1474    [Xtestfile1]
   1475    (1,17)  error: ';' missing
   1476    (21,2)  warning: variable 'z' not defined
   1477    (67,3)  error: end of file found before string ended
   1478    --
   1479 
   1480    [Xtestfile2]
   1481    --
   1482 
   1483    [Xtestfile3]
   1484    NEW compiler v1.1
   1485    (2,2)   warning: variable 'x' not defined
   1486    (67,3)  warning: 's' already defined
   1487    --
   1488  [DATA]
   1489 
   1490  set efm=%+P[%f]%r,(%l\\,%c)%*[\ ]%t%*[^:]:\ %m,%+Q--%r
   1491  " To exercise the push/pop file functionality in quickfix, the test files
   1492  " need to be created.
   1493  call writefile(['Line1'], 'Xtestfile1')
   1494  call writefile(['Line2'], 'Xtestfile2')
   1495  call writefile(['Line3'], 'Xtestfile3')
   1496  cexpr ""
   1497  for l in lines
   1498      caddexpr l
   1499  endfor
   1500  let l = getqflist()
   1501  call assert_equal(12, len(l))
   1502  call assert_equal(21, l[2].lnum)
   1503  call assert_equal(2, l[2].col)
   1504  call assert_equal('w', l[2].type)
   1505  call assert_equal('e', l[3].type)
   1506  call delete('Xtestfile1')
   1507  call delete('Xtestfile2')
   1508  call delete('Xtestfile3')
   1509 
   1510  " Test for %P, %Q with non-existing files
   1511  cexpr lines
   1512  let l = getqflist()
   1513  call assert_equal(14, len(l))
   1514  call assert_equal('[Xtestfile1]', l[0].text)
   1515  call assert_equal('[Xtestfile2]', l[6].text)
   1516  call assert_equal('[Xtestfile3]', l[9].text)
   1517 
   1518  " Tests for %E, %C and %Z format specifiers
   1519  let lines =<< trim [DATA]
   1520    Error 275
   1521    line 42
   1522    column 3
   1523    ' ' expected after '--'
   1524  [DATA]
   1525 
   1526  set efm=%EError\ %n,%Cline\ %l,%Ccolumn\ %c,%Z%m
   1527  cgetexpr lines
   1528  let l = getqflist()
   1529  call assert_equal(275, l[0].nr)
   1530  call assert_equal(42, l[0].lnum)
   1531  call assert_equal(3, l[0].col)
   1532  call assert_equal('E', l[0].type)
   1533  call assert_equal("\n' ' expected after '--'", l[0].text)
   1534 
   1535  " Test for %>
   1536  let lines =<< trim [DATA]
   1537    Error in line 147 of foo.c:
   1538    unknown variable 'i'
   1539  [DATA]
   1540 
   1541  set efm=unknown\ variable\ %m,%E%>Error\ in\ line\ %l\ of\ %f:,%Z%m
   1542  cgetexpr lines
   1543  let l = getqflist()
   1544  call assert_equal(147, l[0].lnum)
   1545  call assert_equal('E', l[0].type)
   1546  call assert_equal("\nunknown variable 'i'", l[0].text)
   1547 
   1548  " Test for %A, %C and other formats
   1549  let lines =<< trim [DATA]
   1550    ==============================================================
   1551    FAIL: testGetTypeIdCachesResult (dbfacadeTest.DjsDBFacadeTest)
   1552    --------------------------------------------------------------
   1553    Traceback (most recent call last):
   1554      File "unittests/dbfacadeTest.py", line 89, in testFoo
   1555        self.assertEquals(34, dtid)
   1556      File "/usr/lib/python2.2/unittest.py", line 286, in
   1557     failUnlessEqual
   1558        raise self.failureException, \\
   1559    W:AssertionError: 34 != 33
   1560 
   1561    --------------------------------------------------------------
   1562    Ran 27 tests in 0.063s
   1563  [DATA]
   1564 
   1565  set efm=%C\ %.%#,%A\ \ File\ \"%f\"\\,\ line\ %l%.%#,%Z%[%^\ ]%\\@=%t:%m
   1566  cgetexpr lines
   1567  let l = getqflist()
   1568  call assert_equal(8, len(l))
   1569  call assert_equal(89, l[4].lnum)
   1570  call assert_equal(1, l[4].valid)
   1571  call assert_equal('unittests/dbfacadeTest.py', bufname(l[4].bufnr))
   1572  call assert_equal('W', l[4].type)
   1573 
   1574  " Test for %o
   1575  set efm=%f(%o):%l\ %m
   1576  cgetexpr ['Xotestfile(Language.PureScript.Types):20 Error']
   1577  call writefile(['Line1'], 'Xotestfile')
   1578  let l = getqflist()
   1579  call assert_equal(1, len(l), string(l))
   1580  call assert_equal('Language.PureScript.Types', l[0].module)
   1581  copen
   1582  call assert_equal('Language.PureScript.Types|20| Error', getline(1))
   1583  call feedkeys("\<CR>", 'xn')
   1584  call assert_equal('Xotestfile', expand('%:t'))
   1585  cclose
   1586  bd
   1587  call delete("Xotestfile")
   1588 
   1589  " Test for a long module name
   1590  cexpr 'Xtest(' . repeat('m', 1026) . '):15 message'
   1591  let l = getqflist()
   1592  " call assert_equal(repeat('m', 1024), l[0].module)
   1593  call assert_equal(repeat('m', 1023), l[0].module)
   1594  call assert_equal(15, l[0].lnum)
   1595  call assert_equal('message', l[0].text)
   1596 
   1597  " The following sequence of commands used to crash Vim
   1598  set efm=%W%m
   1599  cgetexpr ['msg1']
   1600  let l = getqflist()
   1601  call assert_equal(1, len(l), string(l))
   1602  call assert_equal('msg1', l[0].text)
   1603  set efm=%C%m
   1604  lexpr 'msg2'
   1605  let l = getloclist(0)
   1606  call assert_equal(1, len(l), string(l))
   1607  call assert_equal('msg2', l[0].text)
   1608  lopen
   1609  call setqflist([], 'r')
   1610  caddbuf
   1611  let l = getqflist()
   1612  call assert_equal(1, len(l), string(l))
   1613  call assert_equal('|| msg2', l[0].text)
   1614 
   1615  " When matching error lines, case should be ignored. Test for this.
   1616  set noignorecase
   1617  let l=getqflist({'lines' : ['Xtest:FOO10:Line 20'], 'efm':'%f:foo%l:%m'})
   1618  call assert_equal(10, l.items[0].lnum)
   1619  call assert_equal('Line 20', l.items[0].text)
   1620  set ignorecase&
   1621 
   1622  new | only
   1623  let &efm = save_efm
   1624 endfunc
   1625 
   1626 " Test for '%t' (error type) field in 'efm'
   1627 func Test_efm_error_type()
   1628  let save_efm = &efm
   1629 
   1630  " error type
   1631  set efm=%f:%l:%t:%m
   1632  let lines =<< trim END
   1633    Xfile1:10:E:msg1
   1634    Xfile1:20:W:msg2
   1635    Xfile1:30:I:msg3
   1636    Xfile1:40:N:msg4
   1637    Xfile1:50:R:msg5
   1638  END
   1639  cexpr lines
   1640  let output = split(execute('clist'), "\n")
   1641  call assert_equal([
   1642        \ ' 1 Xfile1:10 error: msg1',
   1643        \ ' 2 Xfile1:20 warning: msg2',
   1644        \ ' 3 Xfile1:30 info: msg3',
   1645        \ ' 4 Xfile1:40 note: msg4',
   1646        \ ' 5 Xfile1:50 R: msg5'], output)
   1647 
   1648  " error type and a error number
   1649  set efm=%f:%l:%t:%n:%m
   1650  let lines =<< trim END
   1651    Xfile1:10:E:2:msg1
   1652    Xfile1:20:W:4:msg2
   1653    Xfile1:30:I:6:msg3
   1654    Xfile1:40:N:8:msg4
   1655    Xfile1:50:R:3:msg5
   1656  END
   1657  cexpr lines
   1658  let output = split(execute('clist'), "\n")
   1659  call assert_equal([
   1660        \ ' 1 Xfile1:10 error   2: msg1',
   1661        \ ' 2 Xfile1:20 warning   4: msg2',
   1662        \ ' 3 Xfile1:30 info   6: msg3',
   1663        \ ' 4 Xfile1:40 note   8: msg4',
   1664        \ ' 5 Xfile1:50 R   3: msg5'], output)
   1665  let &efm = save_efm
   1666 endfunc
   1667 
   1668 " Test for end_lnum ('%e') and end_col ('%k') fields in 'efm'
   1669 func Test_efm_end_lnum_col()
   1670  let save_efm = &efm
   1671 
   1672  " single line
   1673  set efm=%f:%l-%e:%c-%k:%t:%m
   1674  cexpr ["Xfile1:10-20:1-2:E:msg1", "Xfile1:20-30:2-3:W:msg2",]
   1675  let output = split(execute('clist'), "\n")
   1676  call assert_equal([
   1677        \ ' 1 Xfile1:10-20 col 1-2 error: msg1',
   1678        \ ' 2 Xfile1:20-30 col 2-3 warning: msg2'], output)
   1679 
   1680  " multiple lines
   1681  set efm=%A%n)%m,%Z%f:%l-%e:%c-%k
   1682  let lines =<< trim END
   1683    1)msg1
   1684    Xfile1:14-24:1-2
   1685    2)msg2
   1686    Xfile1:24-34:3-4
   1687  END
   1688  cexpr lines
   1689  let output = split(execute('clist'), "\n")
   1690  call assert_equal([
   1691        \ ' 1 Xfile1:14-24 col 1-2 error   1: msg1',
   1692        \ ' 2 Xfile1:24-34 col 3-4 error   2: msg2'], output)
   1693  let &efm = save_efm
   1694 endfunc
   1695 
   1696 func XquickfixChangedByAutocmd(cchar)
   1697  call s:setup_commands(a:cchar)
   1698  if a:cchar == 'c'
   1699    let ErrorNr = 'E925'
   1700    func! ReadFunc()
   1701      colder
   1702      cgetexpr []
   1703    endfunc
   1704  else
   1705    let ErrorNr = 'E926'
   1706    func! ReadFunc()
   1707      lolder
   1708      lgetexpr []
   1709    endfunc
   1710  endif
   1711 
   1712  augroup QF_Test
   1713    au!
   1714    autocmd BufReadCmd test_changed.txt call ReadFunc()
   1715  augroup END
   1716 
   1717  new | only
   1718  let words = [ "a", "b" ]
   1719  let qflist = []
   1720  for word in words
   1721    call add(qflist, {'filename': 'test_changed.txt'})
   1722    call g:Xsetlist(qflist, ' ')
   1723  endfor
   1724  call assert_fails('Xrewind', ErrorNr . ':')
   1725 
   1726  augroup QF_Test
   1727    au!
   1728  augroup END
   1729 
   1730  if a:cchar == 'c'
   1731    cexpr ["Xtest1:1:Line"]
   1732    cwindow
   1733    only
   1734    augroup QF_Test
   1735      au!
   1736      autocmd WinEnter * call setqflist([], 'f')
   1737    augroup END
   1738    call assert_fails('exe "normal \<CR>"', 'E925:')
   1739    augroup QF_Test
   1740      au!
   1741    augroup END
   1742  endif
   1743  %bw!
   1744 endfunc
   1745 
   1746 func Test_quickfix_was_changed_by_autocmd()
   1747  call XquickfixChangedByAutocmd('c')
   1748  call XquickfixChangedByAutocmd('l')
   1749 endfunc
   1750 
   1751 func Test_setloclist_in_autocommand()
   1752  call writefile(['test1', 'test2'], 'Xfile')
   1753  edit Xfile
   1754  let s:bufnr = bufnr()
   1755  call setloclist(1,
   1756        \ [{'bufnr' : s:bufnr, 'lnum' : 1, 'text' : 'test1'},
   1757        \  {'bufnr' : s:bufnr, 'lnum' : 2, 'text' : 'test2'}])
   1758 
   1759  augroup Test_LocList
   1760    au!
   1761    autocmd BufEnter * call setloclist(1,
   1762          \ [{'bufnr' : s:bufnr, 'lnum' : 1, 'text' : 'test1'},
   1763          \  {'bufnr' : s:bufnr, 'lnum' : 2, 'text' : 'test2'}], 'r')
   1764  augroup END
   1765 
   1766  lopen
   1767  call assert_fails('exe "normal j\<CR>"', 'E926:')
   1768 
   1769  augroup Test_LocList
   1770    au!
   1771  augroup END
   1772  call delete('Xfile')
   1773 endfunc
   1774 
   1775 func Test_caddbuffer_to_empty()
   1776  helpgr quickfix
   1777  call setqflist([], 'r')
   1778  cad
   1779  try
   1780    cn
   1781  catch
   1782    " number of matches is unknown
   1783    call assert_true(v:exception =~ 'E553:')
   1784  endtry
   1785  quit!
   1786 endfunc
   1787 
   1788 func Test_cgetexpr_works()
   1789  " this must not crash Vim
   1790  cgetexpr [$x]
   1791  lgetexpr [$x]
   1792 endfunc
   1793 
   1794 " Tests for the setqflist() and setloclist() functions
   1795 func SetXlistTests(cchar, bnum)
   1796  call s:setup_commands(a:cchar)
   1797 
   1798  call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 1},
   1799        \  {'bufnr': a:bnum, 'lnum': 2, 'end_lnum': 3, 'col': 4, 'end_col': 5, 'user_data': {'6': [7, 8]}}])
   1800  let l = g:Xgetlist()
   1801  call assert_equal(2, len(l))
   1802  call assert_equal(2, l[1].lnum)
   1803  call assert_equal(3, l[1].end_lnum)
   1804  call assert_equal(4, l[1].col)
   1805  call assert_equal(5, l[1].end_col)
   1806  call assert_equal({'6': [7, 8]}, l[1].user_data)
   1807 
   1808  " Test that user_data is garbage collected
   1809  call g:Xsetlist([{'user_data': ['high', 5]},
   1810        \  {'user_data': {'this': [7, 'eight'], 'is': ['a', 'dictionary']}}])
   1811  call test_garbagecollect_now()
   1812  let l = g:Xgetlist()
   1813  call assert_equal(2, len(l))
   1814  call assert_equal(['high', 5], l[0].user_data)
   1815  call assert_equal({'this': [7, 'eight'], 'is': ['a', 'dictionary']}, l[1].user_data)
   1816 
   1817  Xnext
   1818  call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 3}], 'a')
   1819  let l = g:Xgetlist()
   1820  call assert_equal(3, len(l))
   1821  Xnext
   1822  call assert_equal(3, line('.'))
   1823 
   1824  " Appending entries to the list should not change the cursor position
   1825  " in the quickfix window
   1826  Xwindow
   1827  1
   1828  call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 4},
   1829       \  {'bufnr': a:bnum, 'lnum': 5}], 'a')
   1830  call assert_equal(1, line('.'))
   1831  close
   1832 
   1833  call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 3},
   1834       \  {'bufnr': a:bnum, 'lnum': 4},
   1835       \  {'bufnr': a:bnum, 'lnum': 5}], 'r')
   1836  let l = g:Xgetlist()
   1837  call assert_equal(3, len(l))
   1838  call assert_equal(5, l[2].lnum)
   1839 
   1840  call g:Xsetlist([])
   1841  let l = g:Xgetlist()
   1842  call assert_equal(0, len(l))
   1843 
   1844  " Tests for setting the 'valid' flag
   1845  call g:Xsetlist([{'bufnr':a:bnum, 'lnum':4, 'valid':0}])
   1846  Xwindow
   1847  call assert_equal(1, winnr('$'))
   1848  let l = g:Xgetlist()
   1849  call g:Xsetlist(l)
   1850  call assert_equal(0, g:Xgetlist()[0].valid)
   1851  " Adding a non-valid entry should not mark the list as having valid entries
   1852  call g:Xsetlist([{'bufnr':a:bnum, 'lnum':5, 'valid':0}], 'a')
   1853  Xwindow
   1854  call assert_equal(1, winnr('$'))
   1855 
   1856  " :cnext/:cprev should still work even with invalid entries in the list
   1857  let l = [{'bufnr' : a:bnum, 'lnum' : 1, 'text' : '1', 'valid' : 0},
   1858       \ {'bufnr' : a:bnum, 'lnum' : 2, 'text' : '2', 'valid' : 0}]
   1859  call g:Xsetlist(l)
   1860  Xnext
   1861  call assert_equal(2, g:Xgetlist({'idx' : 0}).idx)
   1862  Xprev
   1863  call assert_equal(1, g:Xgetlist({'idx' : 0}).idx)
   1864  " :cnext/:cprev should still work after appending invalid entries to an
   1865  " empty list
   1866  call g:Xsetlist([])
   1867  call g:Xsetlist(l, 'a')
   1868  Xnext
   1869  call assert_equal(2, g:Xgetlist({'idx' : 0}).idx)
   1870  Xprev
   1871  call assert_equal(1, g:Xgetlist({'idx' : 0}).idx)
   1872 
   1873  call g:Xsetlist([{'text':'Text1', 'valid':1}])
   1874  Xwindow
   1875  call assert_equal(2, winnr('$'))
   1876  Xclose
   1877  let save_efm = &efm
   1878  set efm=%m
   1879  Xgetexpr 'TestMessage'
   1880  let l = g:Xgetlist()
   1881  call g:Xsetlist(l)
   1882  call assert_equal(1, g:Xgetlist()[0].valid)
   1883  let &efm = save_efm
   1884 
   1885  " Error cases:
   1886  " Refer to a non-existing buffer and pass a non-dictionary type
   1887  call assert_fails("call g:Xsetlist([{'bufnr':998, 'lnum':4}," .
   1888       \ " {'bufnr':999, 'lnum':5}])", 'E92:')
   1889  call g:Xsetlist([[1, 2,3]])
   1890  call assert_equal(0, len(g:Xgetlist()))
   1891  call assert_fails('call g:Xsetlist([], [])', 'E928:')
   1892  call g:Xsetlist([v:_null_dict])
   1893  call assert_equal([], g:Xgetlist())
   1894 endfunc
   1895 
   1896 func Test_setqflist()
   1897  new Xtestfile | only
   1898  let bnum = bufnr('%')
   1899  call setline(1, range(1,5))
   1900 
   1901  call SetXlistTests('c', bnum)
   1902  call SetXlistTests('l', bnum)
   1903 
   1904  enew!
   1905  call delete('Xtestfile')
   1906 endfunc
   1907 
   1908 func Xlist_empty_middle(cchar)
   1909  call s:setup_commands(a:cchar)
   1910 
   1911  " create three quickfix lists
   1912  let @/ = 'Test_'
   1913  Xvimgrep // test_quickfix.vim
   1914  let testlen = len(g:Xgetlist())
   1915  call assert_true(testlen > 0)
   1916  Xvimgrep empty test_quickfix.vim
   1917  call assert_true(len(g:Xgetlist()) > 0)
   1918  Xvimgrep matches test_quickfix.vim
   1919  let matchlen = len(g:Xgetlist())
   1920  call assert_true(matchlen > 0)
   1921  Xolder
   1922  " make the middle list empty
   1923  call g:Xsetlist([], 'r')
   1924  call assert_true(len(g:Xgetlist()) == 0)
   1925  Xolder
   1926  call assert_equal(testlen, len(g:Xgetlist()))
   1927  Xnewer
   1928  Xnewer
   1929  call assert_equal(matchlen, len(g:Xgetlist()))
   1930 endfunc
   1931 
   1932 func Test_setqflist_empty_middle()
   1933  call Xlist_empty_middle('c')
   1934  call Xlist_empty_middle('l')
   1935 endfunc
   1936 
   1937 func Xlist_empty_older(cchar)
   1938  call s:setup_commands(a:cchar)
   1939 
   1940  " create three quickfix lists
   1941  Xvimgrep one test_quickfix.vim
   1942  let onelen = len(g:Xgetlist())
   1943  call assert_true(onelen > 0)
   1944  Xvimgrep two test_quickfix.vim
   1945  let twolen = len(g:Xgetlist())
   1946  call assert_true(twolen > 0)
   1947  Xvimgrep three test_quickfix.vim
   1948  let threelen = len(g:Xgetlist())
   1949  call assert_true(threelen > 0)
   1950  Xolder 2
   1951  " make the first list empty, check the others didn't change
   1952  call g:Xsetlist([], 'r')
   1953  call assert_true(len(g:Xgetlist()) == 0)
   1954  Xnewer
   1955  call assert_equal(twolen, len(g:Xgetlist()))
   1956  Xnewer
   1957  call assert_equal(threelen, len(g:Xgetlist()))
   1958 endfunc
   1959 
   1960 func Test_setqflist_empty_older()
   1961  call Xlist_empty_older('c')
   1962  call Xlist_empty_older('l')
   1963 endfunc
   1964 
   1965 func XquickfixSetListWithAct(cchar)
   1966  call s:setup_commands(a:cchar)
   1967 
   1968  let list1 = [{'filename': 'fnameA', 'text': 'A'},
   1969          \    {'filename': 'fnameB', 'text': 'B'}]
   1970  let list2 = [{'filename': 'fnameC', 'text': 'C'},
   1971          \    {'filename': 'fnameD', 'text': 'D'},
   1972          \    {'filename': 'fnameE', 'text': 'E'}]
   1973 
   1974  " {action} is unspecified.  Same as specifying ' '.
   1975  new | only
   1976  silent! Xnewer 99
   1977  call g:Xsetlist(list1)
   1978  call g:Xsetlist(list2)
   1979  let li = g:Xgetlist()
   1980  call assert_equal(3, len(li))
   1981  call assert_equal('C', li[0]['text'])
   1982  call assert_equal('D', li[1]['text'])
   1983  call assert_equal('E', li[2]['text'])
   1984  silent! Xolder
   1985  let li = g:Xgetlist()
   1986  call assert_equal(2, len(li))
   1987  call assert_equal('A', li[0]['text'])
   1988  call assert_equal('B', li[1]['text'])
   1989 
   1990  " {action} is specified ' '.
   1991  new | only
   1992  silent! Xnewer 99
   1993  call g:Xsetlist(list1)
   1994  call g:Xsetlist(list2, ' ')
   1995  let li = g:Xgetlist()
   1996  call assert_equal(3, len(li))
   1997  call assert_equal('C', li[0]['text'])
   1998  call assert_equal('D', li[1]['text'])
   1999  call assert_equal('E', li[2]['text'])
   2000  silent! Xolder
   2001  let li = g:Xgetlist()
   2002  call assert_equal(2, len(li))
   2003  call assert_equal('A', li[0]['text'])
   2004  call assert_equal('B', li[1]['text'])
   2005 
   2006  " {action} is specified 'a'.
   2007  new | only
   2008  silent! Xnewer 99
   2009  call g:Xsetlist(list1)
   2010  call g:Xsetlist(list2, 'a')
   2011  let li = g:Xgetlist()
   2012  call assert_equal(5, len(li))
   2013  call assert_equal('A', li[0]['text'])
   2014  call assert_equal('B', li[1]['text'])
   2015  call assert_equal('C', li[2]['text'])
   2016  call assert_equal('D', li[3]['text'])
   2017  call assert_equal('E', li[4]['text'])
   2018 
   2019  " {action} is specified 'r'.
   2020  new | only
   2021  silent! Xnewer 99
   2022  call g:Xsetlist(list1)
   2023  call g:Xsetlist(list2, 'r')
   2024  let li = g:Xgetlist()
   2025  call assert_equal(3, len(li))
   2026  call assert_equal('C', li[0]['text'])
   2027  call assert_equal('D', li[1]['text'])
   2028  call assert_equal('E', li[2]['text'])
   2029 
   2030  " Test for wrong value.
   2031  new | only
   2032  call assert_fails("call g:Xsetlist(0)", 'E714:')
   2033  call assert_fails("call g:Xsetlist(list1, '')", 'E927:')
   2034  call assert_fails("call g:Xsetlist(list1, 'aa')", 'E927:')
   2035  call assert_fails("call g:Xsetlist(list1, ' a')", 'E927:')
   2036  call assert_fails("call g:Xsetlist(list1, 0)", 'E928:')
   2037 endfunc
   2038 
   2039 func Test_setqflist_invalid_nr()
   2040  " The following command used to crash Vim
   2041  eval []->setqflist(' ', {'nr' : $XXX_DOES_NOT_EXIST})
   2042 endfunc
   2043 
   2044 func Test_setqflist_user_sets_buftype()
   2045  call setqflist([{'text': 'foo'}, {'text': 'bar'}])
   2046  set buftype=quickfix
   2047  call setqflist([], 'a')
   2048  enew
   2049 endfunc
   2050 
   2051 func Test_quickfix_set_list_with_act()
   2052  call XquickfixSetListWithAct('c')
   2053  call XquickfixSetListWithAct('l')
   2054 endfunc
   2055 
   2056 func XLongLinesTests(cchar)
   2057  let l = g:Xgetlist()
   2058 
   2059  call assert_equal(4, len(l))
   2060  call assert_equal(1, l[0].lnum)
   2061  call assert_equal(1, l[0].col)
   2062  call assert_equal(1975, len(l[0].text))
   2063  call assert_equal(2, l[1].lnum)
   2064  call assert_equal(1, l[1].col)
   2065  call assert_equal(4070, len(l[1].text))
   2066  call assert_equal(3, l[2].lnum)
   2067  call assert_equal(1, l[2].col)
   2068  call assert_equal(4070, len(l[2].text))
   2069  call assert_equal(4, l[3].lnum)
   2070  call assert_equal(1, l[3].col)
   2071  call assert_equal(10, len(l[3].text))
   2072 
   2073  call g:Xsetlist([], 'r')
   2074 endfunc
   2075 
   2076 func s:long_lines_tests(cchar)
   2077  call s:setup_commands(a:cchar)
   2078 
   2079  let testfile = 'samples/quickfix.txt'
   2080 
   2081  " file
   2082  exe 'Xgetfile' testfile
   2083  call XLongLinesTests(a:cchar)
   2084 
   2085  " list
   2086  Xexpr readfile(testfile)
   2087  call XLongLinesTests(a:cchar)
   2088 
   2089  " string
   2090  Xexpr join(readfile(testfile), "\n")
   2091  call XLongLinesTests(a:cchar)
   2092 
   2093  " buffer
   2094  exe 'edit' testfile
   2095  exe 'Xbuffer' bufnr('%')
   2096  call XLongLinesTests(a:cchar)
   2097 endfunc
   2098 
   2099 func Test_long_lines()
   2100  call s:long_lines_tests('c')
   2101  call s:long_lines_tests('l')
   2102 endfunc
   2103 
   2104 func Test_cgetfile_on_long_lines()
   2105  " Problematic values if the line is longer than 4096 bytes.  Then 1024 bytes
   2106  " are read at a time.
   2107  for len in [4078, 4079, 4080, 5102, 5103, 5104, 6126, 6127, 6128, 7150, 7151, 7152]
   2108    let lines =<< trim END
   2109      /tmp/file1:1:1:aaa
   2110      /tmp/file2:1:1:%s
   2111      /tmp/file3:1:1:bbb
   2112      /tmp/file4:1:1:ccc
   2113    END
   2114    let lines[1] = substitute(lines[1], '%s', repeat('x', len), '')
   2115    call writefile(lines, 'Xcqetfile.txt')
   2116    cgetfile Xcqetfile.txt
   2117    call assert_equal(4, getqflist(#{size: v:true}).size, 'with length ' .. len)
   2118  endfor
   2119  call delete('Xcqetfile.txt')
   2120 endfunc
   2121 
   2122 func s:create_test_file(filename)
   2123  let l = []
   2124  for i in range(1, 20)
   2125      call add(l, 'Line' . i)
   2126  endfor
   2127  call writefile(l, a:filename)
   2128 endfunc
   2129 
   2130 func Test_switchbuf()
   2131  call s:create_test_file('Xqftestfile1')
   2132  call s:create_test_file('Xqftestfile2')
   2133  call s:create_test_file('Xqftestfile3')
   2134 
   2135  new | only
   2136  edit Xqftestfile1
   2137  let file1_winid = win_getid()
   2138  new Xqftestfile2
   2139  let file2_winid = win_getid()
   2140  let lines =<< trim END
   2141    Xqftestfile1:5:Line5
   2142    Xqftestfile1:6:Line6
   2143    Xqftestfile2:10:Line10
   2144    Xqftestfile2:11:Line11
   2145    Xqftestfile3:15:Line15
   2146    Xqftestfile3:16:Line16
   2147  END
   2148  cgetexpr lines
   2149 
   2150  new
   2151  let winid = win_getid()
   2152  cfirst | cnext
   2153  call assert_equal(winid, win_getid())
   2154  2cnext
   2155  call assert_equal(winid, win_getid())
   2156  2cnext
   2157  call assert_equal(winid, win_getid())
   2158 
   2159  " Test for 'switchbuf' set to search for files in windows in the current
   2160  " tabpage and jump to an existing window (if present)
   2161  set switchbuf=useopen
   2162  enew
   2163  cfirst | cnext
   2164  call assert_equal(file1_winid, win_getid())
   2165  2cnext
   2166  call assert_equal(file2_winid, win_getid())
   2167  2cnext
   2168  call assert_equal(file2_winid, win_getid())
   2169 
   2170  " Test for 'switchbuf' set to search for files in tabpages and jump to an
   2171  " existing tabpage (if present)
   2172  enew | only
   2173  set switchbuf=usetab
   2174  tabedit Xqftestfile1
   2175  tabedit Xqftestfile2
   2176  tabedit Xqftestfile3
   2177  tabfirst
   2178  cfirst | cnext
   2179  call assert_equal(2, tabpagenr())
   2180  2cnext
   2181  call assert_equal(3, tabpagenr())
   2182  6cnext
   2183  call assert_equal(4, tabpagenr())
   2184  2cpfile
   2185  call assert_equal(2, tabpagenr())
   2186  2cnfile
   2187  call assert_equal(4, tabpagenr())
   2188  tabfirst | tabonly | enew
   2189 
   2190  " Test for 'switchbuf' set to open a new window for every file
   2191  set switchbuf=split
   2192  cfirst | cnext
   2193  call assert_equal(1, winnr('$'))
   2194  cnext | cnext
   2195  call assert_equal(2, winnr('$'))
   2196  cnext | cnext
   2197  call assert_equal(3, winnr('$'))
   2198 
   2199  " Test for 'switchbuf' set to open a new tabpage for every file
   2200  set switchbuf=newtab
   2201  enew | only
   2202  cfirst | cnext
   2203  call assert_equal(1, tabpagenr('$'))
   2204  cnext | cnext
   2205  call assert_equal(2, tabpagenr('$'))
   2206  cnext | cnext
   2207  call assert_equal(3, tabpagenr('$'))
   2208  tabfirst | enew | tabonly | only
   2209 
   2210  set switchbuf=uselast
   2211  split
   2212  let last_winid = win_getid()
   2213  copen
   2214  exe "normal 1G\<CR>"
   2215  call assert_equal(last_winid, win_getid())
   2216  enew | only
   2217 
   2218  " With an empty 'switchbuf', jumping to a quickfix entry should open the
   2219  " file in an existing window (if present)
   2220  set switchbuf=
   2221  edit Xqftestfile1
   2222  let file1_winid = win_getid()
   2223  new Xqftestfile2
   2224  let file2_winid = win_getid()
   2225  copen
   2226  exe "normal 1G\<CR>"
   2227  call assert_equal(file1_winid, win_getid())
   2228  copen
   2229  exe "normal 3G\<CR>"
   2230  call assert_equal(file2_winid, win_getid())
   2231  copen | only
   2232  exe "normal 5G\<CR>"
   2233  call assert_equal(2, winnr('$'))
   2234  call assert_equal(1, bufwinnr('Xqftestfile3'))
   2235 
   2236  " If only quickfix window is open in the current tabpage, jumping to an
   2237  " entry with 'switchbuf' set to 'usetab' should search in other tabpages.
   2238  enew | only
   2239  set switchbuf=usetab
   2240  tabedit Xqftestfile1
   2241  tabedit Xqftestfile2
   2242  tabedit Xqftestfile3
   2243  tabfirst
   2244  copen | only
   2245  clast
   2246  call assert_equal(4, tabpagenr())
   2247  tabfirst | tabonly | enew | only
   2248 
   2249  " Jumping to a file that is not present in any of the tabpages and the
   2250  " current tabpage doesn't have any usable windows, should open it in a new
   2251  " window in the current tabpage.
   2252  copen | only
   2253  cfirst
   2254  call assert_equal(1, tabpagenr())
   2255  call assert_equal('Xqftestfile1', @%)
   2256 
   2257  " If opening a file changes 'switchbuf', then the new value should be
   2258  " retained.
   2259  set modeline&vim
   2260  call writefile(["vim: switchbuf=split"], 'Xqftestfile1')
   2261  enew | only
   2262  set switchbuf&vim
   2263  cexpr "Xqftestfile1:1:10"
   2264  call assert_equal('split', &switchbuf)
   2265  call writefile(["vim: switchbuf=usetab"], 'Xqftestfile1')
   2266  enew | only
   2267  set switchbuf=useopen
   2268  cexpr "Xqftestfile1:1:10"
   2269  call assert_equal('usetab', &switchbuf)
   2270  call writefile(["vim: switchbuf&vim"], 'Xqftestfile1')
   2271  enew | only
   2272  set switchbuf=useopen
   2273  cexpr "Xqftestfile1:1:10"
   2274  call assert_equal('uselast', &switchbuf)
   2275 
   2276  call delete('Xqftestfile1')
   2277  call delete('Xqftestfile2')
   2278  call delete('Xqftestfile3')
   2279  set switchbuf&vim
   2280 
   2281  enew | only
   2282 endfunc
   2283 
   2284 func Xadjust_qflnum(cchar)
   2285  call s:setup_commands(a:cchar)
   2286 
   2287  enew | only
   2288 
   2289  let fname = 'Xqftestfile' . a:cchar
   2290  call s:create_test_file(fname)
   2291  exe 'edit ' . fname
   2292 
   2293  Xgetexpr [fname . ':5:Line5',
   2294       \ fname . ':10:Line10',
   2295       \ fname . ':15:Line15',
   2296       \ fname . ':20:Line20']
   2297 
   2298  6,14delete
   2299  call append(6, ['Buffer', 'Window'])
   2300 
   2301  let l = g:Xgetlist()
   2302  call assert_equal(5, l[0].lnum)
   2303  call assert_equal(6, l[2].lnum)
   2304  call assert_equal(13, l[3].lnum)
   2305 
   2306  " If a file doesn't have any quickfix entries, then deleting lines in the
   2307  " file should not update the quickfix list
   2308  call g:Xsetlist([], 'f')
   2309  1,2delete
   2310  call assert_equal([], g:Xgetlist())
   2311 
   2312  enew!
   2313  call delete(fname)
   2314 endfunc
   2315 
   2316 func Test_adjust_lnum()
   2317  call setloclist(0, [])
   2318  call Xadjust_qflnum('c')
   2319  call setqflist([])
   2320  call Xadjust_qflnum('l')
   2321 endfunc
   2322 
   2323 " Tests for the :grep/:lgrep and :grepadd/:lgrepadd commands
   2324 func s:test_xgrep(cchar)
   2325  call s:setup_commands(a:cchar)
   2326 
   2327  " The following lines are used for the grep test. Don't remove.
   2328  " Grep_Test_Text: Match 1
   2329  " Grep_Test_Text: Match 2
   2330  " GrepAdd_Test_Text: Match 1
   2331  " GrepAdd_Test_Text: Match 2
   2332  enew! | only
   2333  set makeef&vim
   2334  silent Xgrep Grep_Test_Text: test_quickfix.vim
   2335  call assert_true(len(g:Xgetlist()) == 5)
   2336  Xopen
   2337  call assert_true(w:quickfix_title =~ '^:grep')
   2338  Xclose
   2339  enew
   2340  set makeef=Temp_File_##
   2341  silent Xgrepadd GrepAdd_Test_Text: test_quickfix.vim
   2342  call assert_true(len(g:Xgetlist()) == 9)
   2343 
   2344  " Try with 'grepprg' set to 'internal'
   2345  set grepprg=internal
   2346  silent Xgrep Grep_Test_Text: test_quickfix.vim
   2347  silent Xgrepadd GrepAdd_Test_Text: test_quickfix.vim
   2348  call assert_true(len(g:Xgetlist()) == 9)
   2349  set grepprg&vim
   2350 
   2351  call writefile(['Vim'], 'XtestTempFile')
   2352  set makeef=XtestTempFile
   2353  silent Xgrep Grep_Test_Text: test_quickfix.vim
   2354  call assert_equal(5, len(g:Xgetlist()))
   2355  call assert_false(filereadable('XtestTempFile'))
   2356  set makeef&vim
   2357 endfunc
   2358 
   2359 func Test_grep()
   2360  " The grepprg may not be set on non-Unix systems
   2361  CheckUnix
   2362 
   2363  call s:test_xgrep('c')
   2364  call s:test_xgrep('l')
   2365 endfunc
   2366 
   2367 func Test_local_grepformat()
   2368  let save_grepformat = &grepformat
   2369  set grepformat=%f:%l:%m
   2370  " The following line are used for the local grep test. Don't remove.
   2371  " UNIQUEPREFIX:2:3: Local grepformat test
   2372  new
   2373  setlocal grepformat=UNIQUEPREFIX:%c:%n:%m
   2374  call assert_equal('UNIQUEPREFIX:%c:%n:%m', &l:grepformat)
   2375  call assert_equal('%f:%l:%m', &g:grepformat)
   2376 
   2377  set grepprg=internal
   2378  silent grep "^[[:space:]]*\" UNIQUEPREFIX:" test_quickfix.vim
   2379  call assert_equal(1, len(getqflist()))
   2380  set grepprg&vim
   2381 
   2382  bwipe!
   2383  let &grepformat = save_grepformat
   2384 endfunc
   2385 
   2386 func Test_two_windows()
   2387  " Use one 'errorformat' for two windows.  Add an expression to each of them,
   2388  " make sure they each keep their own state.
   2389  set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f'
   2390  call mkdir('Xone/a', 'p')
   2391  call mkdir('Xtwo/a', 'p')
   2392  let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7']
   2393  call writefile(lines, 'Xone/a/one.txt')
   2394  call writefile(lines, 'Xtwo/a/two.txt')
   2395 
   2396  new one
   2397  let one_id = win_getid()
   2398  lexpr ""
   2399  new two
   2400  let two_id = win_getid()
   2401  lexpr ""
   2402 
   2403  laddexpr "Entering dir 'Xtwo/a'"
   2404  call win_gotoid(one_id)
   2405  laddexpr "Entering dir 'Xone/a'"
   2406  call win_gotoid(two_id)
   2407  laddexpr 'two.txt:5:two two two'
   2408  call win_gotoid(one_id)
   2409  laddexpr 'one.txt:3:one one one'
   2410 
   2411  let loc_one = getloclist(one_id)
   2412  call assert_equal('Xone/a/one.txt', bufname(loc_one[1].bufnr))
   2413  call assert_equal(3, loc_one[1].lnum)
   2414 
   2415  let loc_two = getloclist(two_id)
   2416  call assert_equal('Xtwo/a/two.txt', bufname(loc_two[1].bufnr))
   2417  call assert_equal(5, loc_two[1].lnum)
   2418 
   2419  call win_gotoid(one_id)
   2420  bwipe!
   2421  call win_gotoid(two_id)
   2422  bwipe!
   2423  call delete('Xone', 'rf')
   2424  call delete('Xtwo', 'rf')
   2425 endfunc
   2426 
   2427 func XbottomTests(cchar)
   2428  call s:setup_commands(a:cchar)
   2429 
   2430  " Calling lbottom without any errors should fail
   2431  if a:cchar == 'l'
   2432      call assert_fails('lbottom', 'E776:')
   2433  endif
   2434 
   2435  call g:Xsetlist([{'filename': 'foo', 'lnum': 42}])
   2436  Xopen
   2437  let wid = win_getid()
   2438  call assert_equal(1, line('.'))
   2439  wincmd w
   2440  call g:Xsetlist([{'filename': 'var', 'lnum': 24}], 'a')
   2441  Xbottom
   2442  call win_gotoid(wid)
   2443  call assert_equal(2, line('.'))
   2444  Xclose
   2445 endfunc
   2446 
   2447 " Tests for the :cbottom and :lbottom commands
   2448 func Test_cbottom()
   2449  call XbottomTests('c')
   2450  call XbottomTests('l')
   2451 endfunc
   2452 
   2453 func HistoryTest(cchar)
   2454  call s:setup_commands(a:cchar)
   2455 
   2456  " clear all lists after the first one, then replace the first one.
   2457  call g:Xsetlist([])
   2458  call assert_fails('Xolder 99', 'E380:')
   2459  let entry = {'filename': 'foo', 'lnum': 42}
   2460  call g:Xsetlist([entry], 'r')
   2461  call g:Xsetlist([entry, entry])
   2462  call g:Xsetlist([entry, entry, entry])
   2463  let res = split(execute(a:cchar . 'hist'), "\n")
   2464  call assert_equal(3, len(res))
   2465  let common = 'errors     :set' . (a:cchar == 'c' ? 'qf' : 'loc') . 'list()'
   2466  call assert_equal('  error list 1 of 3; 1 ' . common, res[0])
   2467  call assert_equal('  error list 2 of 3; 2 ' . common, res[1])
   2468  call assert_equal('> error list 3 of 3; 3 ' . common, res[2])
   2469 
   2470  " Test for changing the quickfix lists
   2471  call assert_equal(3, g:Xgetlist({'nr' : 0}).nr)
   2472  exe '1' . a:cchar . 'hist'
   2473  call assert_equal(1, g:Xgetlist({'nr' : 0}).nr)
   2474  exe '3' . a:cchar . 'hist'
   2475  call assert_equal(3, g:Xgetlist({'nr' : 0}).nr)
   2476  call assert_fails('-2' . a:cchar . 'hist', 'E16:')
   2477  call assert_fails('4' . a:cchar . 'hist', 'E16:')
   2478 
   2479  call g:Xsetlist([], 'f')
   2480  let l = split(execute(a:cchar . 'hist'), "\n")
   2481  call assert_equal('No entries', l[0])
   2482  if a:cchar == 'c'
   2483    call assert_fails('4chist', 'E16:')
   2484  else
   2485    call assert_fails('4lhist', 'E776:')
   2486  endif
   2487 
   2488  " An empty list should still show the stack history
   2489  call g:Xsetlist([])
   2490  let res = split(execute(a:cchar . 'hist'), "\n")
   2491  call assert_equal('> error list 1 of 1; 0 ' . common, res[0])
   2492 
   2493  call g:Xsetlist([], 'f')
   2494 endfunc
   2495 
   2496 func Test_history()
   2497  call HistoryTest('c')
   2498  call HistoryTest('l')
   2499 endfunc
   2500 
   2501 func Test_duplicate_buf()
   2502  " make sure we can get the highest buffer number
   2503  edit DoesNotExist
   2504  edit DoesNotExist2
   2505  let last_buffer = bufnr("$")
   2506 
   2507  " make sure only one buffer is created
   2508  call writefile(['this one', 'that one'], 'Xgrepthis')
   2509  vimgrep one Xgrepthis
   2510  vimgrep one Xgrepthis
   2511  call assert_equal(last_buffer + 1, bufnr("$"))
   2512 
   2513  call delete('Xgrepthis')
   2514 endfunc
   2515 
   2516 " Quickfix/Location list set/get properties tests
   2517 func Xproperty_tests(cchar)
   2518  call s:setup_commands(a:cchar)
   2519 
   2520  " Error cases
   2521  call assert_fails('call g:Xgetlist(99)', 'E715:')
   2522  call assert_fails('call g:Xsetlist(99)', 'E714:')
   2523  call assert_fails('call g:Xsetlist([], "a", [])', 'E715:')
   2524 
   2525  " Set and get the title
   2526  call g:Xsetlist([])
   2527  Xopen
   2528  wincmd p
   2529  call g:Xsetlist([{'filename':'foo', 'lnum':27}])
   2530  let s = g:Xsetlist([], 'a', {'title' : 'Sample'})
   2531  call assert_equal(0, s)
   2532  let d = g:Xgetlist({"title":1})
   2533  call assert_equal('Sample', d.title)
   2534  " Try setting title to a non-string value
   2535  call assert_equal(-1, g:Xsetlist([], 'a', {'title' : ['Test']}))
   2536  call assert_equal('Sample', g:Xgetlist({"title":1}).title)
   2537 
   2538  Xopen
   2539  call assert_equal('Sample', w:quickfix_title)
   2540  Xclose
   2541 
   2542  " Tests for action argument
   2543  silent! Xolder 999
   2544  let qfnr = g:Xgetlist({'all':1}).nr
   2545  call g:Xsetlist([], 'r', {'title' : 'N1'})
   2546  call assert_equal('N1', g:Xgetlist({'all':1}).title)
   2547  call g:Xsetlist([], ' ', {'title' : 'N2'})
   2548  call assert_equal(qfnr + 1, g:Xgetlist({'all':1}).nr)
   2549 
   2550  let res = g:Xgetlist({'nr': 0})
   2551  call assert_equal(qfnr + 1, res.nr)
   2552  call assert_equal(['nr'], keys(res))
   2553 
   2554  call g:Xsetlist([], ' ', {'title' : 'N3'})
   2555  call assert_equal('N2', g:Xgetlist({'nr':2, 'title':1}).title)
   2556 
   2557  " Changing the title of an earlier quickfix list
   2558  call g:Xsetlist([], 'r', {'title' : 'NewTitle', 'nr' : 2})
   2559  call assert_equal('NewTitle', g:Xgetlist({'nr':2, 'title':1}).title)
   2560 
   2561  " Changing the title of an invalid quickfix list
   2562  call assert_equal(-1, g:Xsetlist([], ' ',
   2563        \ {'title' : 'SomeTitle', 'nr' : 99}))
   2564  call assert_equal(-1, g:Xsetlist([], ' ',
   2565        \ {'title' : 'SomeTitle', 'nr' : 'abc'}))
   2566 
   2567  if a:cchar == 'c'
   2568    copen
   2569    call assert_equal({'winid':win_getid()}, getqflist({'winid':1}))
   2570    cclose
   2571  endif
   2572 
   2573  " Invalid arguments
   2574  call assert_fails('call g:Xgetlist([])', 'E715')
   2575  call assert_fails('call g:Xsetlist([], "a", [])', 'E715')
   2576  let s = g:Xsetlist([], 'a', {'abc':1})
   2577  call assert_equal(-1, s)
   2578 
   2579  call assert_equal({}, g:Xgetlist({'abc':1}))
   2580  call assert_equal('', g:Xgetlist({'nr':99, 'title':1}).title)
   2581  call assert_equal('', g:Xgetlist({'nr':[], 'title':1}).title)
   2582 
   2583  if a:cchar == 'l'
   2584    call assert_equal({}, getloclist(99, {'title': 1}))
   2585  endif
   2586 
   2587  " Context related tests
   2588  let s = g:Xsetlist([], 'a', {'context':[1,2,3]})
   2589  call assert_equal(0, s)
   2590  call test_garbagecollect_now()
   2591  let d = g:Xgetlist({'context':1})
   2592  call assert_equal([1,2,3], d.context)
   2593  call g:Xsetlist([], 'a', {'context':{'color':'green'}})
   2594  let d = g:Xgetlist({'context':1})
   2595  call assert_equal({'color':'green'}, d.context)
   2596  call g:Xsetlist([], 'a', {'context':"Context info"})
   2597  let d = g:Xgetlist({'context':1})
   2598  call assert_equal("Context info", d.context)
   2599  call g:Xsetlist([], 'a', {'context':246})
   2600  let d = g:Xgetlist({'context':1})
   2601  call assert_equal(246, d.context)
   2602  " set other Vim data types as context
   2603  call g:Xsetlist([], 'a', {'context' : v:_null_blob})
   2604  if has('channel')
   2605    call g:Xsetlist([], 'a', {'context' : test_null_channel()})
   2606  endif
   2607  if has('job')
   2608    call g:Xsetlist([], 'a', {'context' : test_null_job()})
   2609  endif
   2610  " Nvim doesn't have null functions
   2611  " call g:Xsetlist([], 'a', {'context' : test_null_function()})
   2612  " Nvim doesn't have null partials
   2613  " call g:Xsetlist([], 'a', {'context' : test_null_partial()})
   2614  call g:Xsetlist([], 'a', {'context' : ''})
   2615  call test_garbagecollect_now()
   2616  if a:cchar == 'l'
   2617    " Test for copying context across two different location lists
   2618    new | only
   2619    let w1_id = win_getid()
   2620    let l = [1]
   2621    call setloclist(0, [], 'a', {'context':l})
   2622    new
   2623    let w2_id = win_getid()
   2624    call add(l, 2)
   2625    call assert_equal([1, 2], getloclist(w1_id, {'context':1}).context)
   2626    call assert_equal([1, 2], getloclist(w2_id, {'context':1}).context)
   2627    unlet! l
   2628    call assert_equal([1, 2], getloclist(w2_id, {'context':1}).context)
   2629    only
   2630    call setloclist(0, [], 'f')
   2631    call assert_equal('', getloclist(0, {'context':1}).context)
   2632  endif
   2633 
   2634  " Test for changing the context of previous quickfix lists
   2635  call g:Xsetlist([], 'f')
   2636  Xexpr "One"
   2637  Xexpr "Two"
   2638  Xexpr "Three"
   2639  call g:Xsetlist([], 'r', {'context' : [1], 'nr' : 1})
   2640  call g:Xsetlist([], 'a', {'context' : [2], 'nr' : 2})
   2641  " Also, check for setting the context using quickfix list number zero.
   2642  call g:Xsetlist([], 'r', {'context' : [3], 'nr' : 0})
   2643  call test_garbagecollect_now()
   2644  let l = g:Xgetlist({'nr' : 1, 'context' : 1})
   2645  call assert_equal([1], l.context)
   2646  let l = g:Xgetlist({'nr' : 2, 'context' : 1})
   2647  call assert_equal([2], l.context)
   2648  let l = g:Xgetlist({'nr' : 3, 'context' : 1})
   2649  call assert_equal([3], l.context)
   2650 
   2651  " Test for changing the context through reference and for garbage
   2652  " collection of quickfix context
   2653  let l = ["red"]
   2654  call g:Xsetlist([], ' ', {'context' : l})
   2655  call add(l, "blue")
   2656  let x = g:Xgetlist({'context' : 1})
   2657  call add(x.context, "green")
   2658  call assert_equal(["red", "blue", "green"], l)
   2659  call assert_equal(["red", "blue", "green"], x.context)
   2660  unlet l
   2661  call test_garbagecollect_now()
   2662  let m = g:Xgetlist({'context' : 1})
   2663  call assert_equal(["red", "blue", "green"], m.context)
   2664 
   2665  " Test for setting/getting items
   2666  Xexpr ""
   2667  let qfprev = g:Xgetlist({'nr':0})
   2668  let s = g:Xsetlist([], ' ', {'title':'Green',
   2669        \ 'items' : [{'filename':'F1', 'lnum':10}]})
   2670  call assert_equal(0, s)
   2671  let qfcur = g:Xgetlist({'nr':0})
   2672  call assert_true(qfcur.nr == qfprev.nr + 1)
   2673  let l = g:Xgetlist({'items':1})
   2674  call assert_equal('F1', bufname(l.items[0].bufnr))
   2675  call assert_equal(10, l.items[0].lnum)
   2676  call g:Xsetlist([], 'a', {'items' : [{'filename':'F2', 'lnum':20},
   2677        \  {'filename':'F2', 'lnum':30}]})
   2678  let l = g:Xgetlist({'items':1})
   2679  call assert_equal('F2', bufname(l.items[2].bufnr))
   2680  call assert_equal(30, l.items[2].lnum)
   2681  call g:Xsetlist([], 'r', {'items' : [{'filename':'F3', 'lnum':40}]})
   2682  let l = g:Xgetlist({'items':1})
   2683  call assert_equal('F3', bufname(l.items[0].bufnr))
   2684  call assert_equal(40, l.items[0].lnum)
   2685  call g:Xsetlist([], 'r', {'items' : []})
   2686  let l = g:Xgetlist({'items':1})
   2687  call assert_equal(0, len(l.items))
   2688 
   2689  call g:Xsetlist([], 'r', {'title' : 'TestTitle'})
   2690  call g:Xsetlist([], 'r', {'items' : [{'filename' : 'F1', 'lnum' : 10, 'text' : 'L10'}]})
   2691  call g:Xsetlist([], 'r', {'items' : [{'filename' : 'F1', 'lnum' : 10, 'text' : 'L10'}]})
   2692  call assert_equal('TestTitle', g:Xgetlist({'title' : 1}).title)
   2693 
   2694  " Test for getting id of window associated with a location list window
   2695  if a:cchar == 'l'
   2696    only
   2697    call assert_equal(0, g:Xgetlist({'all' : 1}).filewinid)
   2698    let wid = win_getid()
   2699    Xopen
   2700    call assert_equal(wid, g:Xgetlist({'filewinid' : 1}).filewinid)
   2701    wincmd w
   2702    call assert_equal(0, g:Xgetlist({'filewinid' : 1}).filewinid)
   2703    only
   2704  endif
   2705 
   2706  " The following used to crash Vim with address sanitizer
   2707  call g:Xsetlist([], 'f')
   2708  call g:Xsetlist([], 'a', {'items' : [{'filename':'F1', 'lnum':10}]})
   2709  call assert_equal(10, g:Xgetlist({'items':1}).items[0].lnum)
   2710 
   2711  " Try setting the items using a string
   2712  call assert_equal(-1, g:Xsetlist([], ' ', {'items' : 'Test'}))
   2713 
   2714  " Save and restore the quickfix stack
   2715  call g:Xsetlist([], 'f')
   2716  call assert_equal(0, g:Xgetlist({'nr':'$'}).nr)
   2717  Xexpr "File1:10:Line1"
   2718  Xexpr "File2:20:Line2"
   2719  Xexpr "File3:30:Line3"
   2720  let last_qf = g:Xgetlist({'nr':'$'}).nr
   2721  call assert_equal(3, last_qf)
   2722  let qstack = []
   2723  for i in range(1, last_qf)
   2724    let qstack = add(qstack, g:Xgetlist({'nr':i, 'all':1}))
   2725  endfor
   2726  call g:Xsetlist([], 'f')
   2727  for i in range(len(qstack))
   2728    call g:Xsetlist([], ' ', qstack[i])
   2729  endfor
   2730  call assert_equal(3, g:Xgetlist({'nr':'$'}).nr)
   2731  call assert_equal(10, g:Xgetlist({'nr':1, 'items':1}).items[0].lnum)
   2732  call assert_equal(20, g:Xgetlist({'nr':2, 'items':1}).items[0].lnum)
   2733  call assert_equal(30, g:Xgetlist({'nr':3, 'items':1}).items[0].lnum)
   2734  call g:Xsetlist([], 'f')
   2735 
   2736  " Swap two quickfix lists
   2737  Xexpr "File1:10:Line10"
   2738  Xexpr "File2:20:Line20"
   2739  Xexpr "File3:30:Line30"
   2740  call g:Xsetlist([], 'r', {'nr':1,'title':'Colors','context':['Colors']})
   2741  call g:Xsetlist([], 'r', {'nr':2,'title':'Fruits','context':['Fruits']})
   2742  let l1=g:Xgetlist({'nr':1,'all':1})
   2743  let l2=g:Xgetlist({'nr':2,'all':1})
   2744  let save_id = l1.id
   2745  let l1.id=l2.id
   2746  let l2.id=save_id
   2747  call g:Xsetlist([], 'r', l1)
   2748  call g:Xsetlist([], 'r', l2)
   2749  let newl1=g:Xgetlist({'nr':1,'all':1})
   2750  let newl2=g:Xgetlist({'nr':2,'all':1})
   2751  call assert_equal('Fruits', newl1.title)
   2752  call assert_equal(['Fruits'], newl1.context)
   2753  call assert_equal('Line20', newl1.items[0].text)
   2754  call assert_equal('Colors', newl2.title)
   2755  call assert_equal(['Colors'], newl2.context)
   2756  call assert_equal('Line10', newl2.items[0].text)
   2757  call g:Xsetlist([], 'f')
   2758 
   2759  " Cannot specify both a non-empty list argument and a dict argument
   2760  call assert_fails("call g:Xsetlist([{}], ' ', {})", 'E475:')
   2761 endfunc
   2762 
   2763 func Test_qf_property()
   2764  call Xproperty_tests('c')
   2765  call Xproperty_tests('l')
   2766 endfunc
   2767 
   2768 " Test for setting the current index in the location/quickfix list
   2769 func Xtest_setqfidx(cchar)
   2770  call s:setup_commands(a:cchar)
   2771 
   2772  Xgetexpr "F1:10:1:Line1\nF2:20:2:Line2\nF3:30:3:Line3"
   2773  Xgetexpr "F4:10:1:Line1\nF5:20:2:Line2\nF6:30:3:Line3"
   2774  Xgetexpr "F7:10:1:Line1\nF8:20:2:Line2\nF9:30:3:Line3"
   2775 
   2776  call g:Xsetlist([], 'a', {'nr' : 3, 'idx' : 2})
   2777  call g:Xsetlist([], 'a', {'nr' : 2, 'idx' : 2})
   2778  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 3})
   2779  Xolder 2
   2780  Xopen
   2781  call assert_equal(3, line('.'))
   2782  Xnewer
   2783  call assert_equal(2, line('.'))
   2784  Xnewer
   2785  call assert_equal(2, line('.'))
   2786  " Update the current index with the quickfix window open
   2787  wincmd w
   2788  call g:Xsetlist([], 'a', {'nr' : 3, 'idx' : 3})
   2789  Xopen
   2790  call assert_equal(3, line('.'))
   2791  Xclose
   2792 
   2793  " Set the current index to the last entry
   2794  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : '$'})
   2795  call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx)
   2796  " A large value should set the index to the last index
   2797  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 1})
   2798  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 999})
   2799  call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx)
   2800  " Invalid index values
   2801  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : -1})
   2802  call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx)
   2803  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 0})
   2804  call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx)
   2805  call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 'xx'})
   2806  call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx)
   2807  call assert_fails("call g:Xsetlist([], 'a', {'nr':1, 'idx':[]})", 'E745:')
   2808 
   2809  call g:Xsetlist([], 'f')
   2810  new | only
   2811 endfunc
   2812 
   2813 func Test_setqfidx()
   2814  call Xtest_setqfidx('c')
   2815  call Xtest_setqfidx('l')
   2816 endfunc
   2817 
   2818 " Tests for the QuickFixCmdPre/QuickFixCmdPost autocommands
   2819 func QfAutoCmdHandler(loc, cmd)
   2820  call add(g:acmds, a:loc . a:cmd)
   2821 endfunc
   2822 
   2823 func Test_Autocmd()
   2824  autocmd QuickFixCmdPre * call QfAutoCmdHandler('pre', expand('<amatch>'))
   2825  autocmd QuickFixCmdPost * call QfAutoCmdHandler('post', expand('<amatch>'))
   2826 
   2827  let g:acmds = []
   2828  cexpr "F1:10:Line 10"
   2829  caddexpr "F1:20:Line 20"
   2830  cgetexpr "F1:30:Line 30"
   2831  cexpr ""
   2832  caddexpr ""
   2833  cgetexpr ""
   2834  silent! cexpr non_existing_func()
   2835  silent! caddexpr non_existing_func()
   2836  silent! cgetexpr non_existing_func()
   2837  let l =<< trim END
   2838    precexpr
   2839    postcexpr
   2840    precaddexpr
   2841    postcaddexpr
   2842    precgetexpr
   2843    postcgetexpr
   2844    precexpr
   2845    postcexpr
   2846    precaddexpr
   2847    postcaddexpr
   2848    precgetexpr
   2849    postcgetexpr
   2850    precexpr
   2851    precaddexpr
   2852    precgetexpr
   2853  END
   2854  call assert_equal(l, g:acmds)
   2855 
   2856  let g:acmds = []
   2857  enew! | call append(0, "F2:10:Line 10")
   2858  cbuffer!
   2859  enew! | call append(0, "F2:20:Line 20")
   2860  cgetbuffer
   2861  enew! | call append(0, "F2:30:Line 30")
   2862  caddbuffer
   2863  new
   2864  let bnum = bufnr('%')
   2865  bunload
   2866  exe 'silent! cbuffer! ' . bnum
   2867  exe 'silent! cgetbuffer ' . bnum
   2868  exe 'silent! caddbuffer ' . bnum
   2869  enew!
   2870  let l =<< trim END
   2871    precbuffer
   2872    postcbuffer
   2873    precgetbuffer
   2874    postcgetbuffer
   2875    precaddbuffer
   2876    postcaddbuffer
   2877    precbuffer
   2878    precgetbuffer
   2879    precaddbuffer
   2880  END
   2881  call assert_equal(l, g:acmds)
   2882 
   2883  call writefile(['Xtest:1:Line1'], 'Xtest')
   2884  call writefile([], 'Xempty')
   2885  let g:acmds = []
   2886  cfile Xtest
   2887  caddfile Xtest
   2888  cgetfile Xtest
   2889  cfile Xempty
   2890  caddfile Xempty
   2891  cgetfile Xempty
   2892  silent! cfile do_not_exist
   2893  silent! caddfile do_not_exist
   2894  silent! cgetfile do_not_exist
   2895  let l =<< trim END
   2896    precfile
   2897    postcfile
   2898    precaddfile
   2899    postcaddfile
   2900    precgetfile
   2901    postcgetfile
   2902    precfile
   2903    postcfile
   2904    precaddfile
   2905    postcaddfile
   2906    precgetfile
   2907    postcgetfile
   2908    precfile
   2909    postcfile
   2910    precaddfile
   2911    postcaddfile
   2912    precgetfile
   2913    postcgetfile
   2914  END
   2915  call assert_equal(l, g:acmds)
   2916 
   2917  let g:acmds = []
   2918  helpgrep quickfix
   2919  silent! helpgrep non_existing_help_topic
   2920  vimgrep test Xtest
   2921  vimgrepadd test Xtest
   2922  silent! vimgrep non_existing_test Xtest
   2923  silent! vimgrepadd non_existing_test Xtest
   2924  set makeprg=
   2925  silent! make
   2926  set makeprg&
   2927  let l =<< trim END
   2928    prehelpgrep
   2929    posthelpgrep
   2930    prehelpgrep
   2931    posthelpgrep
   2932    previmgrep
   2933    postvimgrep
   2934    previmgrepadd
   2935    postvimgrepadd
   2936    previmgrep
   2937    postvimgrep
   2938    previmgrepadd
   2939    postvimgrepadd
   2940    premake
   2941    postmake
   2942  END
   2943  call assert_equal(l, g:acmds)
   2944 
   2945  if has('unix')
   2946    " Run this test only on Unix-like systems. The grepprg may not be set on
   2947    " non-Unix systems.
   2948    " The following lines are used for the grep test. Don't remove.
   2949    " Grep_Autocmd_Text: Match 1
   2950    " GrepAdd_Autocmd_Text: Match 2
   2951    let g:acmds = []
   2952    silent grep Grep_Autocmd_Text test_quickfix.vim
   2953    silent grepadd GrepAdd_Autocmd_Text test_quickfix.vim
   2954    silent grep abc123def Xtest
   2955    silent grepadd abc123def Xtest
   2956    set grepprg=internal
   2957    silent grep Grep_Autocmd_Text test_quickfix.vim
   2958    silent grepadd GrepAdd_Autocmd_Text test_quickfix.vim
   2959    silent lgrep Grep_Autocmd_Text test_quickfix.vim
   2960    silent lgrepadd GrepAdd_Autocmd_Text test_quickfix.vim
   2961    set grepprg&vim
   2962    let l =<< trim END
   2963      pregrep
   2964      postgrep
   2965      pregrepadd
   2966      postgrepadd
   2967      pregrep
   2968      postgrep
   2969      pregrepadd
   2970      postgrepadd
   2971      pregrep
   2972      postgrep
   2973      pregrepadd
   2974      postgrepadd
   2975      prelgrep
   2976      postlgrep
   2977      prelgrepadd
   2978      postlgrepadd
   2979    END
   2980    call assert_equal(l, g:acmds)
   2981  endif
   2982 
   2983  call delete('Xtest')
   2984  call delete('Xempty')
   2985  au! QuickFixCmdPre
   2986  au! QuickFixCmdPost
   2987 endfunc
   2988 
   2989 func Test_Autocmd_Exception()
   2990  set efm=%m
   2991  lgetexpr '?'
   2992 
   2993  try
   2994    call DoesNotExit()
   2995  catch
   2996    lgetexpr '1'
   2997  finally
   2998    lgetexpr '1'
   2999  endtry
   3000 
   3001  call assert_equal('1', getloclist(0)[0].text)
   3002 
   3003  set efm&vim
   3004 endfunc
   3005 
   3006 func Test_caddbuffer_wrong()
   3007  " This used to cause a memory access in freed memory.
   3008  let save_efm = &efm
   3009  set efm=%EEEE%m,%WWWW,%+CCCC%>%#,%GGGG%.#
   3010  cgetexpr ['WWWW', 'EEEE', 'CCCC']
   3011  let &efm = save_efm
   3012  caddbuffer
   3013  bwipe!
   3014 endfunc
   3015 
   3016 func Test_caddexpr_wrong()
   3017  " This used to cause a memory access in freed memory.
   3018  cbuffer
   3019  cbuffer
   3020  copen
   3021  let save_efm = &efm
   3022  set efm=%
   3023  call assert_fails('caddexpr ""', 'E376:')
   3024  let &efm = save_efm
   3025 endfunc
   3026 
   3027 func Test_dirstack_cleanup()
   3028  " This used to cause a memory access in freed memory.
   3029  let save_efm = &efm
   3030  lexpr '0'
   3031  lopen
   3032  fun X(c)
   3033    let save_efm=&efm
   3034    set efm=%D%f
   3035    if a:c == 'c'
   3036      caddexpr '::'
   3037    else
   3038      laddexpr ':0:0'
   3039    endif
   3040    let &efm=save_efm
   3041  endfun
   3042  call X('c')
   3043  call X('l')
   3044  call setqflist([], 'r')
   3045  caddbuffer
   3046  let &efm = save_efm
   3047 endfunc
   3048 
   3049 " Tests for jumping to entries from the location list window and quickfix
   3050 " window
   3051 func Test_cwindow_jump()
   3052  set efm=%f%%%l%%%m
   3053  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
   3054  lopen | only
   3055  lfirst
   3056  call assert_true(winnr('$') == 2)
   3057  call assert_true(winnr() == 1)
   3058  " Location list for the new window should be set
   3059  call assert_true(getloclist(0)[2].text == 'Line 30')
   3060 
   3061  " Open a scratch buffer
   3062  " Open a new window and create a location list
   3063  " Open the location list window and close the other window
   3064  " Jump to an entry.
   3065  " Should create a new window and jump to the entry. The scratch buffer
   3066  " should not be used.
   3067  enew | only
   3068  set buftype=nofile
   3069  below new
   3070  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
   3071  lopen
   3072  2wincmd c
   3073  lnext
   3074  call assert_true(winnr('$') == 3)
   3075  call assert_true(winnr() == 2)
   3076 
   3077  " Open two windows with two different location lists
   3078  " Open the location list window and close the previous window
   3079  " Jump to an entry in the location list window
   3080  " Should open the file in the first window and not set the location list.
   3081  enew | only
   3082  lgetexpr ["F1%5%Line 5"]
   3083  below new
   3084  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
   3085  lopen
   3086  2wincmd c
   3087  lnext
   3088  call assert_true(winnr() == 1)
   3089  call assert_true(getloclist(0)[0].text == 'Line 5')
   3090 
   3091  enew | only
   3092  cgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
   3093  copen
   3094  cnext
   3095  call assert_true(winnr('$') == 2)
   3096  call assert_true(winnr() == 1)
   3097 
   3098  " open the quickfix buffer in two windows and jump to an entry. Should open
   3099  " the file in the first quickfix window.
   3100  enew | only
   3101  copen
   3102  let bnum = bufnr('')
   3103  exe 'sbuffer ' . bnum
   3104  wincmd b
   3105  cfirst
   3106  call assert_equal(2, winnr())
   3107  call assert_equal('F1', @%)
   3108  enew | only
   3109  exe 'sb' bnum
   3110  exe 'botright sb' bnum
   3111  wincmd t
   3112  clast
   3113  call assert_equal(2, winnr())
   3114  call assert_equal('quickfix', getwinvar(1, '&buftype'))
   3115  call assert_equal('quickfix', getwinvar(3, '&buftype'))
   3116 
   3117  " Jumping to a file from the location list window should find a usable
   3118  " window by wrapping around the window list.
   3119  enew | only
   3120  call setloclist(0, [], 'f')
   3121  new | new
   3122  lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
   3123  lopen
   3124  1close
   3125  call assert_equal(0, getloclist(3, {'id' : 0}).id)
   3126  lnext
   3127  call assert_equal(3, winnr())
   3128  call assert_equal(getloclist(1, {'id' : 0}).id, getloclist(3, {'id' : 0}).id)
   3129 
   3130  enew | only
   3131  set efm&vim
   3132 endfunc
   3133 
   3134 func Test_cwindow_highlight()
   3135  CheckScreendump
   3136 
   3137  let lines =<< trim END
   3138    call setline(1, ['some', 'text', 'with', 'matches'])
   3139    write XCwindow
   3140    vimgrep e XCwindow
   3141    redraw
   3142    cwindow 4
   3143  END
   3144  call writefile(lines, 'XtestCwindow')
   3145  let buf = RunVimInTerminal('-S XtestCwindow', #{rows: 12})
   3146  call VerifyScreenDump(buf, 'Test_quickfix_cwindow_1', {})
   3147 
   3148  call term_sendkeys(buf, ":cnext\<CR>")
   3149  call VerifyScreenDump(buf, 'Test_quickfix_cwindow_2', {})
   3150 
   3151  " clean up
   3152  call StopVimInTerminal(buf)
   3153  call delete('XtestCwindow')
   3154  call delete('XCwindow')
   3155 endfunc
   3156 
   3157 func XvimgrepTests(cchar)
   3158  call s:setup_commands(a:cchar)
   3159 
   3160  let lines =<< trim END
   3161    Editor:VIM vim
   3162    Editor:Emacs EmAcS
   3163    Editor:Notepad NOTEPAD
   3164  END
   3165  call writefile(lines, 'Xtestfile1')
   3166  call writefile(['Linux', 'macOS', 'MS-Windows'], 'Xtestfile2')
   3167 
   3168  " Error cases
   3169  call assert_fails('Xvimgrep /abc *', 'E682:')
   3170 
   3171  let @/=''
   3172  call assert_fails('Xvimgrep // *', 'E35:')
   3173 
   3174  call assert_fails('Xvimgrep abc', 'E683:')
   3175  call assert_fails('Xvimgrep a1b2c3 Xtestfile1', 'E480:')
   3176  call assert_fails('Xvimgrep pat Xa1b2c3', 'E480:')
   3177 
   3178  Xexpr ""
   3179  Xvimgrepadd Notepad Xtestfile1
   3180  Xvimgrepadd macOS Xtestfile2
   3181  let l = g:Xgetlist()
   3182  call assert_equal(2, len(l))
   3183  call assert_equal('Editor:Notepad NOTEPAD', l[0].text)
   3184 
   3185  10Xvimgrep #\cvim#g Xtestfile?
   3186  let l = g:Xgetlist()
   3187  call assert_equal(2, len(l))
   3188  call assert_equal(8, l[0].col)
   3189  call assert_equal(11, l[0].end_col)
   3190  call assert_equal(12, l[1].col)
   3191  call assert_equal(15, l[1].end_col)
   3192 
   3193  1Xvimgrep ?Editor? Xtestfile*
   3194  let l = g:Xgetlist()
   3195  call assert_equal(1, len(l))
   3196  call assert_equal('Editor:VIM vim', l[0].text)
   3197 
   3198  edit +3 Xtestfile2
   3199  Xvimgrep +\cemacs+j Xtestfile1
   3200  let l = g:Xgetlist()
   3201  call assert_equal('Xtestfile2', @%)
   3202  call assert_equal('Editor:Emacs EmAcS', l[0].text)
   3203 
   3204  " Test for unloading a buffer after vimgrep searched the buffer
   3205  %bwipe
   3206  Xvimgrep /Editor/j Xtestfile*
   3207  call assert_equal(0, getbufinfo('Xtestfile1')[0].loaded)
   3208  call assert_equal([], getbufinfo('Xtestfile2'))
   3209 
   3210  " Test for opening the dummy buffer used by vimgrep in a window. The new
   3211  " window should be closed
   3212  %bw!
   3213  augroup QF_Test
   3214    au!
   3215    autocmd BufReadPre * exe "sb " .. expand("<abuf>")
   3216  augroup END
   3217  call assert_fails("Xvimgrep /sublime/ Xtestfile1", 'E480:')
   3218  call assert_equal(1, winnr('$'))
   3219  augroup QF_Test
   3220    au!
   3221  augroup END
   3222 
   3223  call delete('Xtestfile1')
   3224  call delete('Xtestfile2')
   3225 endfunc
   3226 
   3227 " Tests for the :vimgrep command
   3228 func Test_vimgrep()
   3229  call XvimgrepTests('c')
   3230  call XvimgrepTests('l')
   3231 endfunc
   3232 
   3233 func Test_vimgrep_wildcards_expanded_once()
   3234  new X[id-01] file.txt
   3235  call setline(1, 'some text to search for')
   3236  vimgrep text %
   3237  bwipe!
   3238 endfunc
   3239 
   3240 " Test for incsearch highlighting of the :vimgrep pattern
   3241 " This test used to cause "E315: ml_get: invalid lnum" errors.
   3242 func Test_vimgrep_incsearch()
   3243  enew
   3244  set incsearch
   3245  call Ntest_override("char_avail", 1)
   3246 
   3247  call feedkeys(":2vimgrep assert test_quickfix.vim test_cdo.vim\<CR>", "ntx")
   3248  let l = getqflist()
   3249  call assert_equal(2, len(l))
   3250 
   3251  call Ntest_override("ALL", 0)
   3252  set noincsearch
   3253 endfunc
   3254 
   3255 " Test vimgrep with the last search pattern not set
   3256 func Test_vimgrep_with_no_last_search_pat()
   3257  let lines =<< trim [SCRIPT]
   3258    call assert_fails('vimgrep // *', 'E35:')
   3259    call writefile(v:errors, 'Xresult')
   3260    qall!
   3261  [SCRIPT]
   3262  call writefile(lines, 'Xscript')
   3263  if RunVim([], [], '--clean -S Xscript')
   3264    call assert_equal([], readfile('Xresult'))
   3265  endif
   3266  call delete('Xscript')
   3267  call delete('Xresult')
   3268 endfunc
   3269 
   3270 " Test vimgrep without swap file
   3271 func Test_vimgrep_without_swap_file()
   3272  let lines =<< trim [SCRIPT]
   3273    vimgrep grep test_c*
   3274    call writefile(['done'], 'Xresult')
   3275    qall!
   3276  [SCRIPT]
   3277  call writefile(lines, 'Xscript')
   3278  if RunVim([], [], '--clean -n -S Xscript Xscript')
   3279    call assert_equal(['done'], readfile('Xresult'))
   3280  endif
   3281  call delete('Xscript')
   3282  call delete('Xresult')
   3283 endfunc
   3284 
   3285 func Test_vimgrep_existing_swapfile()
   3286  call writefile(['match apple with apple'], 'Xapple')
   3287  call writefile(['swapfile'], '.Xapple.swp')
   3288  let g:foundSwap = 0
   3289  let g:ignoreSwapExists = 1
   3290  augroup grep
   3291    au SwapExists * let foundSwap = 1 | let v:swapchoice = 'e'
   3292  augroup END
   3293  vimgrep apple Xapple
   3294  call assert_equal(1, g:foundSwap)
   3295  call assert_match('.Xapple.swo', swapname(''))
   3296 
   3297  call delete('Xapple')
   3298  call delete('.Xapple.swp')
   3299  augroup grep
   3300    au! SwapExists
   3301  augroup END
   3302  unlet g:ignoreSwapExists
   3303 endfunc
   3304 
   3305 func XfreeTests(cchar)
   3306  call s:setup_commands(a:cchar)
   3307 
   3308  enew | only
   3309 
   3310  " Deleting the quickfix stack should work even When the current list is
   3311  " somewhere in the middle of the stack
   3312  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
   3313  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
   3314  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
   3315  Xolder
   3316  call g:Xsetlist([], 'f')
   3317  call assert_equal(0, len(g:Xgetlist()))
   3318 
   3319  " After deleting the stack, adding a new list should create a stack with a
   3320  " single list.
   3321  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
   3322  call assert_equal(1, g:Xgetlist({'all':1}).nr)
   3323 
   3324  " Deleting the stack from a quickfix window should update/clear the
   3325  " quickfix/location list window.
   3326  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
   3327  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
   3328  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
   3329  Xolder
   3330  Xwindow
   3331  call g:Xsetlist([], 'f')
   3332  call assert_equal(2, winnr('$'))
   3333  call assert_equal(1, line('$'))
   3334  Xclose
   3335 
   3336  " Deleting the stack from a non-quickfix window should update/clear the
   3337  " quickfix/location list window.
   3338  Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
   3339  Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
   3340  Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
   3341  Xolder
   3342  Xwindow
   3343  wincmd p
   3344  call g:Xsetlist([], 'f')
   3345  call assert_equal(0, len(g:Xgetlist()))
   3346  wincmd p
   3347  call assert_equal(2, winnr('$'))
   3348  call assert_equal(1, line('$'))
   3349 
   3350  " After deleting the location list stack, if the location list window is
   3351  " opened, then a new location list should be created. So opening the
   3352  " location list window again should not create a new window.
   3353  if a:cchar == 'l'
   3354      lexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
   3355      wincmd p
   3356      lopen
   3357      call assert_equal(2, winnr('$'))
   3358  endif
   3359  Xclose
   3360 endfunc
   3361 
   3362 " Tests for the quickfix free functionality
   3363 func Test_qf_free()
   3364  call XfreeTests('c')
   3365  call XfreeTests('l')
   3366 endfunc
   3367 
   3368 " Test for buffer overflow when parsing lines and adding new entries to
   3369 " the quickfix list.
   3370 func Test_bufoverflow()
   3371  set efm=%f:%l:%m
   3372  cgetexpr ['File1:100:' . repeat('x', 1025)]
   3373 
   3374  set efm=%+GCompiler:\ %.%#,%f:%l:%m
   3375  cgetexpr ['Compiler: ' . repeat('a', 1015), 'File1:10:Hello World']
   3376 
   3377  set efm=%DEntering\ directory\ %f,%f:%l:%m
   3378  let lines =<< trim eval END
   3379    Entering directory $"{repeat('a', 1006)}"
   3380    File1:10:Hello World
   3381  END
   3382  cgetexpr lines
   3383  set efm&vim
   3384 endfunc
   3385 
   3386 " Tests for getting the quickfix stack size
   3387 func XsizeTests(cchar)
   3388  call s:setup_commands(a:cchar)
   3389 
   3390  call g:Xsetlist([], 'f')
   3391  call assert_equal(0, g:Xgetlist({'nr':'$'}).nr)
   3392  call assert_equal('', g:Xgetlist({'nr':'$', 'all':1}).title)
   3393  call assert_equal(0, g:Xgetlist({'nr':0}).nr)
   3394 
   3395  Xexpr "File1:10:Line1"
   3396  Xexpr "File2:20:Line2"
   3397  Xexpr "File3:30:Line3"
   3398  Xolder | Xolder
   3399  call assert_equal(3, g:Xgetlist({'nr':'$'}).nr)
   3400  call g:Xsetlist([], 'f')
   3401 
   3402  Xexpr "File1:10:Line1"
   3403  Xexpr "File2:20:Line2"
   3404  Xexpr "File3:30:Line3"
   3405  Xolder | Xolder
   3406  call g:Xsetlist([], 'a', {'nr':'$', 'title':'Compiler'})
   3407  call assert_equal('Compiler', g:Xgetlist({'nr':3, 'all':1}).title)
   3408 endfunc
   3409 
   3410 func Test_Qf_Size()
   3411  call XsizeTests('c')
   3412  call XsizeTests('l')
   3413 endfunc
   3414 
   3415 func Test_cclose_from_copen()
   3416    augroup QF_Test
   3417 au!
   3418        au FileType qf :call assert_fails(':cclose', 'E788')
   3419    augroup END
   3420    copen
   3421    augroup QF_Test
   3422 au!
   3423    augroup END
   3424    augroup! QF_Test
   3425 endfunc
   3426 
   3427 func Test_cclose_in_autocmd()
   3428  " Problem is only triggered if "starting" is zero, so that the OptionSet
   3429  " event will be triggered.
   3430  call Ntest_override('starting', 1)
   3431  augroup QF_Test
   3432    au!
   3433    au FileType qf :call assert_fails(':cclose', 'E788')
   3434  augroup END
   3435  copen
   3436  augroup QF_Test
   3437    au!
   3438  augroup END
   3439  augroup! QF_Test
   3440  call Ntest_override('starting', 0)
   3441 endfunc
   3442 
   3443 " Check that ":file" without an argument is possible even when "curbuf->b_ro_locked"
   3444 " is set.
   3445 func Test_file_from_copen()
   3446  " Works without argument.
   3447  augroup QF_Test
   3448    au!
   3449    au FileType qf file
   3450  augroup END
   3451  copen
   3452 
   3453  augroup QF_Test
   3454    au!
   3455  augroup END
   3456  cclose
   3457 
   3458  " Fails with argument.
   3459  augroup QF_Test
   3460    au!
   3461    au FileType qf call assert_fails(':file foo', 'E788')
   3462  augroup END
   3463  copen
   3464  augroup QF_Test
   3465    au!
   3466  augroup END
   3467  cclose
   3468 
   3469  augroup! QF_Test
   3470 endfunc
   3471 
   3472 func Test_resize_from_copen()
   3473  augroup QF_Test
   3474    au!
   3475    au FileType qf resize 5
   3476  augroup END
   3477  try
   3478    " This should succeed without any exception.  No other buffers are
   3479    " involved in the autocmd.
   3480    copen
   3481  finally
   3482    augroup QF_Test
   3483      au!
   3484    augroup END
   3485    augroup! QF_Test
   3486  endtry
   3487 endfunc
   3488 
   3489 func Test_filetype_autocmd()
   3490  " this changes the location list while it is in use to fill a buffer
   3491  lexpr ''
   3492  lopen
   3493  augroup FT_loclist
   3494    au FileType * call setloclist(0, [], 'f')
   3495  augroup END
   3496  silent! lolder
   3497  lexpr ''
   3498 
   3499  augroup FT_loclist
   3500    au! FileType
   3501  augroup END
   3502 endfunc
   3503 
   3504 func Test_vimgrep_with_textlock()
   3505  new
   3506 
   3507  " Simple way to execute something with "textlock" set.
   3508  " Check that vimgrep without jumping can be executed.
   3509  au InsertCharPre * vimgrep /RunTheTest/j runtest.vim
   3510  normal ax
   3511  let qflist = getqflist()
   3512  call assert_true(len(qflist) > 0)
   3513  call assert_match('RunTheTest', qflist[0].text)
   3514  call setqflist([], 'r')
   3515  au! InsertCharPre
   3516 
   3517  " Check that vimgrepadd without jumping can be executed.
   3518  au InsertCharPre * vimgrepadd /RunTheTest/j runtest.vim
   3519  normal ax
   3520  let qflist = getqflist()
   3521  call assert_true(len(qflist) > 0)
   3522  call assert_match('RunTheTest', qflist[0].text)
   3523  call setqflist([], 'r')
   3524  au! InsertCharPre
   3525 
   3526  " Check that lvimgrep without jumping can be executed.
   3527  au InsertCharPre * lvimgrep /RunTheTest/j runtest.vim
   3528  normal ax
   3529  let qflist = getloclist(0)
   3530  call assert_true(len(qflist) > 0)
   3531  call assert_match('RunTheTest', qflist[0].text)
   3532  call setloclist(0, [], 'r')
   3533  au! InsertCharPre
   3534 
   3535  " Check that lvimgrepadd without jumping can be executed.
   3536  au InsertCharPre * lvimgrepadd /RunTheTest/j runtest.vim
   3537  normal ax
   3538  let qflist = getloclist(0)
   3539  call assert_true(len(qflist) > 0)
   3540  call assert_match('RunTheTest', qflist[0].text)
   3541  call setloclist(0, [], 'r')
   3542  au! InsertCharPre
   3543 
   3544  " trying to jump will give an error
   3545  au InsertCharPre * vimgrep /RunTheTest/ runtest.vim
   3546  call assert_fails('normal ax', 'E565:')
   3547  au! InsertCharPre
   3548 
   3549  au InsertCharPre * vimgrepadd /RunTheTest/ runtest.vim
   3550  call assert_fails('normal ax', 'E565:')
   3551  au! InsertCharPre
   3552 
   3553  au InsertCharPre * lvimgrep /RunTheTest/ runtest.vim
   3554  call assert_fails('normal ax', 'E565:')
   3555  au! InsertCharPre
   3556 
   3557  au InsertCharPre * lvimgrepadd /RunTheTest/ runtest.vim
   3558  call assert_fails('normal ax', 'E565:')
   3559  au! InsertCharPre
   3560 
   3561  bwipe!
   3562 endfunc
   3563 
   3564 " Tests for the quickfix buffer b:changedtick variable
   3565 func Xchangedtick_tests(cchar)
   3566  call s:setup_commands(a:cchar)
   3567 
   3568  new | only
   3569 
   3570  Xexpr "" | Xexpr "" | Xexpr ""
   3571 
   3572  Xopen
   3573  Xolder
   3574  Xolder
   3575  Xaddexpr "F1:10:Line10"
   3576  Xaddexpr "F2:20:Line20"
   3577  call g:Xsetlist([{"filename":"F3", "lnum":30, "text":"Line30"}], 'a')
   3578  call g:Xsetlist([], 'f')
   3579  call assert_equal(8, getbufvar('%', 'changedtick'))
   3580  Xclose
   3581 endfunc
   3582 
   3583 func Test_changedtick()
   3584  call Xchangedtick_tests('c')
   3585  call Xchangedtick_tests('l')
   3586 endfunc
   3587 
   3588 " Tests for parsing an expression using setqflist()
   3589 func Xsetexpr_tests(cchar)
   3590  call s:setup_commands(a:cchar)
   3591 
   3592  let t = ["File1:10:Line10", "File1:20:Line20"]
   3593  call g:Xsetlist([], ' ', {'lines' : t})
   3594  call g:Xsetlist([], 'a', {'lines' : ["File1:30:Line30"]})
   3595 
   3596  let l = g:Xgetlist()
   3597  call assert_equal(3, len(l))
   3598  call assert_equal(20, l[1].lnum)
   3599  call assert_equal('Line30', l[2].text)
   3600  call g:Xsetlist([], 'r', {'lines' : ["File2:5:Line5"]})
   3601  let l = g:Xgetlist()
   3602  call assert_equal(1, len(l))
   3603  call assert_equal('Line5', l[0].text)
   3604  call assert_equal(-1, g:Xsetlist([], 'a', {'lines' : 10}))
   3605  call assert_equal(-1, g:Xsetlist([], 'a', {'lines' : "F1:10:L10"}))
   3606 
   3607  call g:Xsetlist([], 'f')
   3608  " Add entries to multiple lists
   3609  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["File1:10:Line10"]})
   3610  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["File2:20:Line20"]})
   3611  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["File1:15:Line15"]})
   3612  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["File2:25:Line25"]})
   3613  call assert_equal('Line15', g:Xgetlist({'nr':1, 'items':1}).items[1].text)
   3614  call assert_equal('Line25', g:Xgetlist({'nr':2, 'items':1}).items[1].text)
   3615 
   3616  " Adding entries using a custom efm
   3617  set efm&
   3618  call g:Xsetlist([], ' ', {'efm' : '%f#%l#%m',
   3619 			\ 'lines' : ["F1#10#L10", "F2#20#L20"]})
   3620  call assert_equal(20, g:Xgetlist({'items':1}).items[1].lnum)
   3621  call g:Xsetlist([], 'a', {'efm' : '%f#%l#%m', 'lines' : ["F3:30:L30"]})
   3622  call assert_equal('F3:30:L30', g:Xgetlist({'items':1}).items[2].text)
   3623  call assert_equal(20, g:Xgetlist({'items':1}).items[1].lnum)
   3624  call assert_equal(-1, g:Xsetlist([], 'a', {'efm' : [],
   3625 			\ 'lines' : ['F1:10:L10']}))
   3626 endfunc
   3627 
   3628 func Test_setexpr()
   3629  call Xsetexpr_tests('c')
   3630  call Xsetexpr_tests('l')
   3631 endfunc
   3632 
   3633 " Tests for per quickfix/location list directory stack
   3634 func Xmultidirstack_tests(cchar)
   3635  call s:setup_commands(a:cchar)
   3636 
   3637  call g:Xsetlist([], 'f')
   3638  Xexpr "" | Xexpr ""
   3639 
   3640  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["Entering dir 'Xone/a'"]})
   3641  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["Entering dir 'Xtwo/a'"]})
   3642  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["one.txt:3:one one one"]})
   3643  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["two.txt:5:two two two"]})
   3644 
   3645  let l1 = g:Xgetlist({'nr':1, 'items':1})
   3646  let l2 = g:Xgetlist({'nr':2, 'items':1})
   3647  call assert_equal('Xone/a/one.txt', bufname(l1.items[1].bufnr))
   3648  call assert_equal(3, l1.items[1].lnum)
   3649  call assert_equal('Xtwo/a/two.txt', bufname(l2.items[1].bufnr))
   3650  call assert_equal(5, l2.items[1].lnum)
   3651 endfunc
   3652 
   3653 func Test_multidirstack()
   3654  call mkdir('Xone/a', 'p')
   3655  call mkdir('Xtwo/a', 'p')
   3656  let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7']
   3657  call writefile(lines, 'Xone/a/one.txt')
   3658  call writefile(lines, 'Xtwo/a/two.txt')
   3659  let save_efm = &efm
   3660  set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f'
   3661 
   3662  call Xmultidirstack_tests('c')
   3663  call Xmultidirstack_tests('l')
   3664 
   3665  let &efm = save_efm
   3666  call delete('Xone', 'rf')
   3667  call delete('Xtwo', 'rf')
   3668 endfunc
   3669 
   3670 " Tests for per quickfix/location list file stack
   3671 func Xmultifilestack_tests(cchar)
   3672  call s:setup_commands(a:cchar)
   3673 
   3674  call g:Xsetlist([], 'f')
   3675  Xexpr "" | Xexpr ""
   3676 
   3677  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["[one.txt]"]})
   3678  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["[two.txt]"]})
   3679  call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["(3,5) one one one"]})
   3680  call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["(5,9) two two two"]})
   3681 
   3682  let l1 = g:Xgetlist({'nr':1, 'items':1})
   3683  let l2 = g:Xgetlist({'nr':2, 'items':1})
   3684  call assert_equal('one.txt', bufname(l1.items[1].bufnr))
   3685  call assert_equal(3, l1.items[1].lnum)
   3686  call assert_equal('two.txt', bufname(l2.items[1].bufnr))
   3687  call assert_equal(5, l2.items[1].lnum)
   3688 
   3689  " Test for start of a new error line in the same line where a previous
   3690  " error line ends with a file stack.
   3691  let efm_val = 'Error\ l%l\ in\ %f,'
   3692  let efm_val .= '%-P%>(%f%r,Error\ l%l\ in\ %m,%-Q)%r'
   3693  let lines =<< trim END
   3694    (one.txt
   3695    Error l4 in one.txt
   3696    ) (two.txt
   3697    Error l6 in two.txt
   3698    )
   3699    Error l8 in one.txt
   3700  END
   3701  let l = g:Xgetlist({'lines': lines, 'efm' : efm_val})
   3702  call assert_equal(3, len(l.items))
   3703  call assert_equal('one.txt', bufname(l.items[0].bufnr))
   3704  call assert_equal(4, l.items[0].lnum)
   3705  call assert_equal('one.txt', l.items[0].text)
   3706  call assert_equal('two.txt', bufname(l.items[1].bufnr))
   3707  call assert_equal(6, l.items[1].lnum)
   3708  call assert_equal('two.txt', l.items[1].text)
   3709  call assert_equal('one.txt', bufname(l.items[2].bufnr))
   3710  call assert_equal(8, l.items[2].lnum)
   3711  call assert_equal('', l.items[2].text)
   3712 endfunc
   3713 
   3714 func Test_multifilestack()
   3715  let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7']
   3716  call writefile(lines, 'one.txt')
   3717  call writefile(lines, 'two.txt')
   3718  let save_efm = &efm
   3719  set efm=%+P[%f],(%l\\,%c)\ %m,%-Q
   3720 
   3721  call Xmultifilestack_tests('c')
   3722  call Xmultifilestack_tests('l')
   3723 
   3724  let &efm = save_efm
   3725  call delete('one.txt')
   3726  call delete('two.txt')
   3727 endfunc
   3728 
   3729 " Tests for per buffer 'efm' setting
   3730 func Test_perbuf_efm()
   3731  call writefile(["File1-10-Line10"], 'one.txt')
   3732  call writefile(["File2#20#Line20"], 'two.txt')
   3733  set efm=%f#%l#%m
   3734  new | only
   3735  new
   3736  setlocal efm=%f-%l-%m
   3737  cfile one.txt
   3738  wincmd w
   3739  caddfile two.txt
   3740 
   3741  let l = getqflist()
   3742  call assert_equal(10, l[0].lnum)
   3743  call assert_equal('Line20', l[1].text)
   3744 
   3745  set efm&
   3746  new | only
   3747  call delete('one.txt')
   3748  call delete('two.txt')
   3749 endfunc
   3750 
   3751 " Open multiple help windows using ":lhelpgrep
   3752 " This test used to crash Vim
   3753 func Test_Multi_LL_Help()
   3754  new | only
   3755  lhelpgrep window
   3756  lopen
   3757  e#
   3758  lhelpgrep buffer
   3759  call assert_equal(3, winnr('$'))
   3760  call assert_true(len(getloclist(1)) != 0)
   3761  call assert_true(len(getloclist(2)) != 0)
   3762  new | only
   3763 endfunc
   3764 
   3765 " Tests for adding new quickfix lists using setqflist()
   3766 func XaddQf_tests(cchar)
   3767  call s:setup_commands(a:cchar)
   3768 
   3769  " Create a new list using ' ' for action
   3770  call g:Xsetlist([], 'f')
   3771  call g:Xsetlist([], ' ', {'title' : 'Test1'})
   3772  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
   3773  call assert_equal(1, l.nr)
   3774  call assert_equal('Test1', l.title)
   3775 
   3776  " Create a new list using ' ' for action and '$' for 'nr'
   3777  call g:Xsetlist([], 'f')
   3778  call g:Xsetlist([], ' ', {'title' : 'Test2', 'nr' : '$'})
   3779  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
   3780  call assert_equal(1, l.nr)
   3781  call assert_equal('Test2', l.title)
   3782 
   3783  " Create a new list using 'a' for action
   3784  call g:Xsetlist([], 'f')
   3785  call g:Xsetlist([], 'a', {'title' : 'Test3'})
   3786  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
   3787  call assert_equal(1, l.nr)
   3788  call assert_equal('Test3', l.title)
   3789 
   3790  " Create a new list using 'a' for action and '$' for 'nr'
   3791  call g:Xsetlist([], 'f')
   3792  call g:Xsetlist([], 'a', {'title' : 'Test3', 'nr' : '$'})
   3793  call g:Xsetlist([], 'a', {'title' : 'Test4'})
   3794  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
   3795  call assert_equal(1, l.nr)
   3796  call assert_equal('Test4', l.title)
   3797 
   3798  " Adding a quickfix list should remove all the lists following the current
   3799  " list.
   3800  Xexpr "" | Xexpr "" | Xexpr ""
   3801  silent! 10Xolder
   3802  call g:Xsetlist([], ' ', {'title' : 'Test5'})
   3803  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
   3804  call assert_equal(2, l.nr)
   3805  call assert_equal('Test5', l.title)
   3806 
   3807  " Add a quickfix list using '$' as the list number.
   3808  let lastqf = g:Xgetlist({'nr':'$'}).nr
   3809  silent! 99Xolder
   3810  call g:Xsetlist([], ' ', {'nr' : '$', 'title' : 'Test6'})
   3811  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
   3812  call assert_equal(lastqf + 1, l.nr)
   3813  call assert_equal('Test6', l.title)
   3814 
   3815  " Add a quickfix list using 'nr' set to one more than the quickfix
   3816  " list size.
   3817  let lastqf = g:Xgetlist({'nr':'$'}).nr
   3818  silent! 99Xolder
   3819  call g:Xsetlist([], ' ', {'nr' : lastqf + 1, 'title' : 'Test7'})
   3820  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
   3821  call assert_equal(lastqf + 1, l.nr)
   3822  call assert_equal('Test7', l.title)
   3823 
   3824  " Add a quickfix list to a stack with 10 lists using 'nr' set to '$'
   3825  exe repeat('Xexpr "" |', 9) . 'Xexpr ""'
   3826  silent! 99Xolder
   3827  call g:Xsetlist([], ' ', {'nr' : '$', 'title' : 'Test8'})
   3828  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
   3829  call assert_equal(10, l.nr)
   3830  call assert_equal('Test8', l.title)
   3831 
   3832  " Add a quickfix list using 'nr' set to a value greater than 10
   3833  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : 12, 'title' : 'Test9'}))
   3834 
   3835  " Try adding a quickfix list with 'nr' set to a value greater than the
   3836  " quickfix list size but less than 10.
   3837  call g:Xsetlist([], 'f')
   3838  Xexpr "" | Xexpr "" | Xexpr ""
   3839  silent! 99Xolder
   3840  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : 8, 'title' : 'Test10'}))
   3841 
   3842  " Add a quickfix list using 'nr' set to a some string or list
   3843  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : [1,2], 'title' : 'Test11'}))
   3844 endfunc
   3845 
   3846 func Test_add_qf()
   3847  call XaddQf_tests('c')
   3848  call XaddQf_tests('l')
   3849 endfunc
   3850 
   3851 " Test for getting the quickfix list items from some text without modifying
   3852 " the quickfix stack
   3853 func XgetListFromLines(cchar)
   3854  call s:setup_commands(a:cchar)
   3855  call g:Xsetlist([], 'f')
   3856 
   3857  let l = g:Xgetlist({'lines' : ["File2:20:Line20", "File2:30:Line30"]}).items
   3858  call assert_equal(2, len(l))
   3859  call assert_equal(30, l[1].lnum)
   3860 
   3861  call assert_equal({}, g:Xgetlist({'lines' : 10}))
   3862  call assert_equal({}, g:Xgetlist({'lines' : 'File1:10:Line10'}))
   3863  call assert_equal([], g:Xgetlist({'lines' : []}).items)
   3864  call assert_equal([], g:Xgetlist({'lines' : [10, 20]}).items)
   3865 
   3866  " Parse text using a custom efm
   3867  set efm&
   3868  let l = g:Xgetlist({'lines':['File3#30#Line30'], 'efm' : '%f#%l#%m'}).items
   3869  call assert_equal('Line30', l[0].text)
   3870  let l = g:Xgetlist({'lines':['File3:30:Line30'], 'efm' : '%f-%l-%m'}).items
   3871  call assert_equal('File3:30:Line30', l[0].text)
   3872  let l = g:Xgetlist({'lines':['File3:30:Line30'], 'efm' : [1,2]})
   3873  call assert_equal({}, l)
   3874  call assert_fails("call g:Xgetlist({'lines':['abc'], 'efm':'%2'})", 'E376:')
   3875  call assert_fails("call g:Xgetlist({'lines':['abc'], 'efm':''})", 'E378:')
   3876 
   3877  " Make sure that the quickfix stack is not modified
   3878  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
   3879 endfunc
   3880 
   3881 func Test_get_list_from_lines()
   3882  call XgetListFromLines('c')
   3883  call XgetListFromLines('l')
   3884 endfunc
   3885 
   3886 " Tests for the quickfix list id
   3887 func Xqfid_tests(cchar)
   3888  call s:setup_commands(a:cchar)
   3889 
   3890  call g:Xsetlist([], 'f')
   3891  call assert_equal(0, g:Xgetlist({'id':0}).id)
   3892  Xexpr ''
   3893  let start_id = g:Xgetlist({'id' : 0}).id
   3894  Xexpr '' | Xexpr ''
   3895  Xolder
   3896  call assert_equal(start_id, g:Xgetlist({'id':0, 'nr':1}).id)
   3897  call assert_equal(start_id + 1, g:Xgetlist({'id':0, 'nr':0}).id)
   3898  call assert_equal(start_id + 2, g:Xgetlist({'id':0, 'nr':'$'}).id)
   3899  call assert_equal(0, g:Xgetlist({'id':0, 'nr':99}).id)
   3900  call assert_equal(2, g:Xgetlist({'id':start_id + 1, 'nr':0}).nr)
   3901  call assert_equal(0, g:Xgetlist({'id':99, 'nr':0}).id)
   3902  call assert_equal(0, g:Xgetlist({'id':"abc", 'nr':0}).id)
   3903 
   3904  call g:Xsetlist([], 'a', {'id':start_id, 'context':[1,2]})
   3905  call assert_equal([1,2], g:Xgetlist({'nr':1, 'context':1}).context)
   3906  call g:Xsetlist([], 'a', {'id':start_id+1, 'lines':['F1:10:L10']})
   3907  call assert_equal('L10', g:Xgetlist({'nr':2, 'items':1}).items[0].text)
   3908  call assert_equal(-1, g:Xsetlist([], 'a', {'id':999, 'title':'Vim'}))
   3909  call assert_equal(-1, g:Xsetlist([], 'a', {'id':'abc', 'title':'Vim'}))
   3910 
   3911  let qfid = g:Xgetlist({'id':0, 'nr':0})
   3912  call g:Xsetlist([], 'f')
   3913  call assert_equal(0, g:Xgetlist({'id':qfid, 'nr':0}).id)
   3914 endfunc
   3915 
   3916 func Test_qf_id()
   3917  call Xqfid_tests('c')
   3918  call Xqfid_tests('l')
   3919 endfunc
   3920 
   3921 func Xqfjump_tests(cchar)
   3922  call s:setup_commands(a:cchar)
   3923 
   3924  call writefile(["Line1\tFoo", "Line2"], 'F1')
   3925  call writefile(["Line1\tBar", "Line2"], 'F2')
   3926  call writefile(["Line1\tBaz", "Line2"], 'F3')
   3927 
   3928  call g:Xsetlist([], 'f')
   3929 
   3930  " Tests for
   3931  "   Jumping to a line using a pattern
   3932  "   Jumping to a column greater than the last column in a line
   3933  "   Jumping to a line greater than the last line in the file
   3934  let l = []
   3935  for i in range(1, 7)
   3936    call add(l, {})
   3937  endfor
   3938  let l[0].filename='F1'
   3939  let l[0].pattern='Line1'
   3940  let l[1].filename='F2'
   3941  let l[1].pattern='Line1'
   3942  let l[2].filename='F3'
   3943  let l[2].pattern='Line1'
   3944  let l[3].filename='F3'
   3945  let l[3].lnum=1
   3946  let l[3].col=9
   3947  let l[3].vcol=1
   3948  let l[4].filename='F3'
   3949  let l[4].lnum=99
   3950  let l[5].filename='F3'
   3951  let l[5].lnum=1
   3952  let l[5].col=99
   3953  let l[5].vcol=1
   3954  let l[6].filename='F3'
   3955  let l[6].pattern='abcxyz'
   3956 
   3957  call g:Xsetlist([], ' ', {'items' : l})
   3958  Xopen | only
   3959  2Xnext
   3960  call assert_equal(3, g:Xgetlist({'idx' : 0}).idx)
   3961  call assert_equal('F3', @%)
   3962  Xnext
   3963  call assert_equal(7, col('.'))
   3964  Xnext
   3965  call assert_equal(2, line('.'))
   3966  Xnext
   3967  call assert_equal(9, col('.'))
   3968  2
   3969  Xnext
   3970  call assert_equal(2, line('.'))
   3971 
   3972  if a:cchar == 'l'
   3973    " When jumping to a location list entry in the location list window and
   3974    " no usable windows are available, then a new window should be opened.
   3975    enew! | new | only
   3976    call g:Xsetlist([], 'f')
   3977    setlocal buftype=nofile
   3978    new
   3979    let lines =<< trim END
   3980      F1:1:1:Line1
   3981      F1:2:2:Line2
   3982      F2:1:1:Line1
   3983      F2:2:2:Line2
   3984      F3:1:1:Line1
   3985      F3:2:2:Line2
   3986    END
   3987    call g:Xsetlist([], ' ', {'lines': lines})
   3988    Xopen
   3989    let winid = win_getid()
   3990    wincmd p
   3991    close
   3992    call win_gotoid(winid)
   3993    Xnext
   3994    call assert_equal(3, winnr('$'))
   3995    call assert_equal(1, winnr())
   3996    call assert_equal(2, line('.'))
   3997 
   3998    " When jumping to an entry in the location list window and the window
   3999    " associated with the location list is not present and a window containing
   4000    " the file is already present, then that window should be used.
   4001    close
   4002    belowright new
   4003    call g:Xsetlist([], 'f')
   4004    edit F3
   4005    call win_gotoid(winid)
   4006    Xlast
   4007    call assert_equal(3, winnr())
   4008    call assert_equal(6, g:Xgetlist({'size' : 1}).size)
   4009    call assert_equal(winid, g:Xgetlist({'winid' : 1}).winid)
   4010  endif
   4011 
   4012  " Cleanup
   4013  enew!
   4014  new | only
   4015 
   4016  call delete('F1')
   4017  call delete('F2')
   4018  call delete('F3')
   4019 endfunc
   4020 
   4021 func Test_qfjump()
   4022  call Xqfjump_tests('c')
   4023  call Xqfjump_tests('l')
   4024 endfunc
   4025 
   4026 " Tests for the getqflist() and getloclist() functions when the list is not
   4027 " present or is empty
   4028 func Xgetlist_empty_tests(cchar)
   4029  call s:setup_commands(a:cchar)
   4030 
   4031  " Empty quickfix stack
   4032  call g:Xsetlist([], 'f')
   4033  call assert_equal('', g:Xgetlist({'context' : 0}).context)
   4034  call assert_equal(0, g:Xgetlist({'id' : 0}).id)
   4035  call assert_equal(0, g:Xgetlist({'idx' : 0}).idx)
   4036  call assert_equal([], g:Xgetlist({'items' : 0}).items)
   4037  call assert_equal(0, g:Xgetlist({'nr' : 0}).nr)
   4038  call assert_equal(0, g:Xgetlist({'size' : 0}).size)
   4039  call assert_equal('', g:Xgetlist({'title' : 0}).title)
   4040  call assert_equal(0, g:Xgetlist({'winid' : 0}).winid)
   4041  call assert_equal(0, g:Xgetlist({'changedtick' : 0}).changedtick)
   4042  if a:cchar == 'c'
   4043    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0,
   4044 	  \ 'items' : [], 'nr' : 0, 'size' : 0, 'qfbufnr' : 0,
   4045 	  \ 'title' : '', 'winid' : 0, 'changedtick': 0,
   4046                  \ 'quickfixtextfunc' : ''}, g:Xgetlist({'all' : 0}))
   4047  else
   4048    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0,
   4049 	\ 'items' : [], 'nr' : 0, 'size' : 0, 'title' : '',
   4050 	\ 'winid' : 0, 'changedtick': 0, 'filewinid' : 0,
   4051 	\ 'qfbufnr' : 0, 'quickfixtextfunc' : ''},
   4052 	\ g:Xgetlist({'all' : 0}))
   4053  endif
   4054 
   4055  " Quickfix window with empty stack
   4056  silent! Xopen
   4057  let qfwinid = (a:cchar == 'c') ? win_getid() : 0
   4058  let qfbufnr = (a:cchar == 'c') ? bufnr('') : 0
   4059  call assert_equal(qfwinid, g:Xgetlist({'winid' : 0}).winid)
   4060  Xclose
   4061 
   4062  " Empty quickfix list
   4063  Xexpr ""
   4064  call assert_equal('', g:Xgetlist({'context' : 0}).context)
   4065  call assert_notequal(0, g:Xgetlist({'id' : 0}).id)
   4066  call assert_equal(0, g:Xgetlist({'idx' : 0}).idx)
   4067  call assert_equal([], g:Xgetlist({'items' : 0}).items)
   4068  call assert_notequal(0, g:Xgetlist({'nr' : 0}).nr)
   4069  call assert_equal(0, g:Xgetlist({'size' : 0}).size)
   4070  call assert_notequal('', g:Xgetlist({'title' : 0}).title)
   4071  call assert_equal(0, g:Xgetlist({'winid' : 0}).winid)
   4072  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
   4073 
   4074  let qfid = g:Xgetlist({'id' : 0}).id
   4075  call g:Xsetlist([], 'f')
   4076 
   4077  " Non-existing quickfix identifier
   4078  call assert_equal('', g:Xgetlist({'id' : qfid, 'context' : 0}).context)
   4079  call assert_equal(0, g:Xgetlist({'id' : qfid}).id)
   4080  call assert_equal(0, g:Xgetlist({'id' : qfid, 'idx' : 0}).idx)
   4081  call assert_equal([], g:Xgetlist({'id' : qfid, 'items' : 0}).items)
   4082  call assert_equal(0, g:Xgetlist({'id' : qfid, 'nr' : 0}).nr)
   4083  call assert_equal(0, g:Xgetlist({'id' : qfid, 'size' : 0}).size)
   4084  call assert_equal('', g:Xgetlist({'id' : qfid, 'title' : 0}).title)
   4085  call assert_equal(0, g:Xgetlist({'id' : qfid, 'winid' : 0}).winid)
   4086  call assert_equal(0, g:Xgetlist({'id' : qfid, 'changedtick' : 0}).changedtick)
   4087  if a:cchar == 'c'
   4088    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
   4089 	\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
   4090 	\ 'qfbufnr' : qfbufnr, 'quickfixtextfunc' : '',
   4091 	\ 'changedtick' : 0}, g:Xgetlist({'id' : qfid, 'all' : 0}))
   4092  else
   4093    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
   4094 	\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
   4095 	\ 'changedtick' : 0, 'filewinid' : 0, 'qfbufnr' : 0,
   4096                \ 'quickfixtextfunc' : ''},
   4097 	\ g:Xgetlist({'id' : qfid, 'all' : 0}))
   4098  endif
   4099 
   4100  " Non-existing quickfix list number
   4101  call assert_equal('', g:Xgetlist({'nr' : 5, 'context' : 0}).context)
   4102  call assert_equal(0, g:Xgetlist({'nr' : 5}).nr)
   4103  call assert_equal(0, g:Xgetlist({'nr' : 5, 'idx' : 0}).idx)
   4104  call assert_equal([], g:Xgetlist({'nr' : 5, 'items' : 0}).items)
   4105  call assert_equal(0, g:Xgetlist({'nr' : 5, 'id' : 0}).id)
   4106  call assert_equal(0, g:Xgetlist({'nr' : 5, 'size' : 0}).size)
   4107  call assert_equal('', g:Xgetlist({'nr' : 5, 'title' : 0}).title)
   4108  call assert_equal(0, g:Xgetlist({'nr' : 5, 'winid' : 0}).winid)
   4109  call assert_equal(0, g:Xgetlist({'nr' : 5, 'changedtick' : 0}).changedtick)
   4110  if a:cchar == 'c'
   4111    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
   4112 	\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
   4113 	\ 'changedtick' : 0, 'qfbufnr' : qfbufnr,
   4114                \ 'quickfixtextfunc' : ''}, g:Xgetlist({'nr' : 5, 'all' : 0}))
   4115  else
   4116    call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
   4117 	\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
   4118 	\ 'changedtick' : 0, 'filewinid' : 0, 'qfbufnr' : 0,
   4119                \ 'quickfixtextfunc' : ''}, g:Xgetlist({'nr' : 5, 'all' : 0}))
   4120  endif
   4121 endfunc
   4122 
   4123 func Test_empty_list_quickfixtextfunc()
   4124  " This was crashing.  Can only reproduce by running it in a separate Vim
   4125  " instance.
   4126  let lines =<< trim END
   4127      func s:Func(o)
   4128              cgetexpr '0'
   4129      endfunc
   4130      cope
   4131      let &quickfixtextfunc = 's:Func'
   4132      cgetfile [ex
   4133  END
   4134  call writefile(lines, 'Xquickfixtextfunc')
   4135  call RunVim([], [], '-e -s -S Xquickfixtextfunc -c qa')
   4136  call delete('Xquickfixtextfunc')
   4137 endfunc
   4138 
   4139 func Test_getqflist()
   4140  call Xgetlist_empty_tests('c')
   4141  call Xgetlist_empty_tests('l')
   4142 endfunc
   4143 
   4144 func Test_getqflist_invalid_nr()
   4145  " The following commands used to crash Vim
   4146  cexpr ""
   4147  call getqflist({'nr' : $XXX_DOES_NOT_EXIST_XXX})
   4148 
   4149  " Cleanup
   4150  call setqflist([], 'r')
   4151 endfunc
   4152 
   4153 " Tests for the quickfix/location list changedtick
   4154 func Xqftick_tests(cchar)
   4155  call s:setup_commands(a:cchar)
   4156 
   4157  call g:Xsetlist([], 'f')
   4158 
   4159  Xexpr "F1:10:Line10"
   4160  let qfid = g:Xgetlist({'id' : 0}).id
   4161  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
   4162  Xaddexpr "F2:20:Line20\nF2:21:Line21"
   4163  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
   4164  call g:Xsetlist([], 'a', {'lines' : ["F3:30:Line30", "F3:31:Line31"]})
   4165  call assert_equal(3, g:Xgetlist({'changedtick' : 0}).changedtick)
   4166  call g:Xsetlist([], 'r', {'lines' : ["F4:40:Line40"]})
   4167  call assert_equal(4, g:Xgetlist({'changedtick' : 0}).changedtick)
   4168  call g:Xsetlist([], 'a', {'title' : 'New Title'})
   4169  call assert_equal(5, g:Xgetlist({'changedtick' : 0}).changedtick)
   4170 
   4171  enew!
   4172  call append(0, ["F5:50:L50", "F6:60:L60"])
   4173  Xaddbuffer
   4174  call assert_equal(6, g:Xgetlist({'changedtick' : 0}).changedtick)
   4175  enew!
   4176 
   4177  call g:Xsetlist([], 'a', {'context' : {'bus' : 'pci'}})
   4178  call assert_equal(7, g:Xgetlist({'changedtick' : 0}).changedtick)
   4179  call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'},
   4180       \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], 'a')
   4181  call assert_equal(8, g:Xgetlist({'changedtick' : 0}).changedtick)
   4182  call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'},
   4183       \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], ' ')
   4184  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
   4185  call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'},
   4186       \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], 'r')
   4187  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
   4188 
   4189  if isdirectory("Xone")
   4190    call delete("Xone", 'rf')
   4191  endif
   4192  call writefile(["F8:80:L80", "F8:81:L81"], "Xone")
   4193  Xfile Xone
   4194  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
   4195  Xaddfile Xone
   4196  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
   4197 
   4198  " Test case for updating a non-current quickfix list
   4199  call g:Xsetlist([], 'f')
   4200  Xexpr "F1:1:L1"
   4201  Xexpr "F2:2:L2"
   4202  call g:Xsetlist([], 'a', {'nr' : 1, "lines" : ["F10:10:L10"]})
   4203  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
   4204  call assert_equal(2, g:Xgetlist({'nr' : 1, 'changedtick' : 0}).changedtick)
   4205 
   4206  call delete("Xone")
   4207 endfunc
   4208 
   4209 func Test_qf_tick()
   4210  call Xqftick_tests('c')
   4211  call Xqftick_tests('l')
   4212 endfunc
   4213 
   4214 " Test helpgrep with lang specifier
   4215 func Xtest_helpgrep_with_lang_specifier(cchar)
   4216  call s:setup_commands(a:cchar)
   4217  Xhelpgrep Vim@en
   4218  call assert_equal('help', &filetype)
   4219  call assert_notequal(0, g:Xgetlist({'nr' : '$'}).nr)
   4220  new | only
   4221 endfunc
   4222 
   4223 func Test_helpgrep_with_lang_specifier()
   4224  call Xtest_helpgrep_with_lang_specifier('c')
   4225  call Xtest_helpgrep_with_lang_specifier('l')
   4226 endfunc
   4227 
   4228 " The following test used to crash Vim.
   4229 " Open the location list window and close the regular window associated with
   4230 " the location list. When the garbage collection runs now, it incorrectly
   4231 " marks the location list context as not in use and frees the context.
   4232 func Test_ll_window_ctx()
   4233  call setloclist(0, [], 'f')
   4234  call setloclist(0, [], 'a', {'context' : []})
   4235  lopen | only
   4236  call test_garbagecollect_now()
   4237  echo getloclist(0, {'context' : 1}).context
   4238  enew | only
   4239 endfunc
   4240 
   4241 " Similar to the problem above, but for user data.
   4242 func Test_ll_window_user_data()
   4243  call setloclist(0, [#{bufnr: bufnr(), user_data: {}}])
   4244  lopen
   4245  wincmd t
   4246  close
   4247  call test_garbagecollect_now()
   4248  call feedkeys("\<CR>", 'tx')
   4249  call test_garbagecollect_now()
   4250  %bwipe!
   4251 endfunc
   4252 
   4253 " The following test used to crash vim
   4254 func Test_lfile_crash()
   4255  sp Xtest
   4256  au QuickFixCmdPre * bw
   4257  call assert_fails('lfile', 'E40:')
   4258  au! QuickFixCmdPre
   4259 endfunc
   4260 
   4261 " The following test used to crash vim
   4262 func Test_lbuffer_crash()
   4263  sv Xtest
   4264  augroup QF_Test
   4265    au!
   4266    au QuickFixCmdPre,QuickFixCmdPost,BufEnter,BufLeave * bw
   4267  augroup END
   4268  lbuffer
   4269  augroup QF_Test
   4270    au!
   4271  augroup END
   4272 endfunc
   4273 
   4274 " The following test used to crash vim
   4275 func Test_lexpr_crash()
   4276  augroup QF_Test
   4277    au!
   4278    au QuickFixCmdPre,QuickFixCmdPost,BufEnter,BufLeave * call setloclist(0, [], 'f')
   4279  augroup END
   4280  lexpr ""
   4281  augroup QF_Test
   4282    au!
   4283  augroup END
   4284 
   4285  enew | only
   4286  augroup QF_Test
   4287    au!
   4288    au BufNew * call setloclist(0, [], 'f')
   4289  augroup END
   4290  lexpr 'x:1:x'
   4291  augroup QF_Test
   4292    au!
   4293  augroup END
   4294 
   4295  enew | only
   4296  lexpr ''
   4297  lopen
   4298  augroup QF_Test
   4299    au!
   4300    au FileType * call setloclist(0, [], 'f')
   4301  augroup END
   4302  lexpr ''
   4303  augroup QF_Test
   4304    au!
   4305  augroup END
   4306 endfunc
   4307 
   4308 " The following test used to crash Vim
   4309 func Test_lvimgrep_crash()
   4310  " this leaves a swapfile .test_quickfix.vim.swp around, why?
   4311  sv Xtest
   4312  augroup QF_Test
   4313    au!
   4314    au QuickFixCmdPre,QuickFixCmdPost,BufEnter,BufLeave * call setloclist(0, [], 'f')
   4315  augroup END
   4316  lvimgrep quickfix test_quickfix.vim
   4317  augroup QF_Test
   4318    au!
   4319  augroup END
   4320 
   4321  new | only
   4322  augroup QF_Test
   4323    au!
   4324    au BufEnter * call setloclist(0, [], 'r')
   4325  augroup END
   4326  call assert_fails('lvimgrep Test_lvimgrep_crash *', 'E926:')
   4327  augroup QF_Test
   4328    au!
   4329  augroup END
   4330 
   4331  enew | only
   4332 endfunc
   4333 
   4334 func Test_lvimgrep_crash2()
   4335  au BufNewFile x sfind
   4336  call assert_fails('lvimgrep x x', 'E471:')
   4337  call assert_fails('lvimgrep x x x', 'E471:')
   4338 
   4339  au! BufNewFile
   4340 endfunc
   4341 
   4342 " Test for the position of the quickfix and location list window
   4343 func Test_qfwin_pos()
   4344  " Open two windows
   4345  new | only
   4346  new
   4347  cexpr ['F1:10:L10']
   4348  copen
   4349  " Quickfix window should be the bottom most window
   4350  call assert_equal(3, winnr())
   4351  close
   4352  " Open at the very top
   4353  wincmd t
   4354  topleft copen
   4355  call assert_equal(1, winnr())
   4356  close
   4357  " open left of the current window
   4358  wincmd t
   4359  below new
   4360  leftabove copen
   4361  call assert_equal(2, winnr())
   4362  close
   4363  " open right of the current window
   4364  rightbelow copen
   4365  call assert_equal(3, winnr())
   4366  close
   4367 endfunc
   4368 
   4369 " Tests for quickfix/location lists changed by autocommands when
   4370 " :vimgrep/:lvimgrep commands are running.
   4371 func Test_vimgrep_autocmd()
   4372  call setqflist([], 'f')
   4373  call writefile(['stars'], 'Xtest1.txt', 'D')
   4374  call writefile(['stars'], 'Xtest2.txt', 'D')
   4375 
   4376  " Test 1:
   4377  " When searching for a pattern using :vimgrep, if the quickfix list is
   4378  " changed by an autocmd, the results should be added to the correct quickfix
   4379  " list.
   4380  autocmd BufRead Xtest2.txt cexpr '' | cexpr ''
   4381  silent vimgrep stars Xtest*.txt
   4382  call assert_equal(1, getqflist({'nr' : 0}).nr)
   4383  call assert_equal(3, getqflist({'nr' : '$'}).nr)
   4384  call assert_equal('Xtest2.txt', bufname(getqflist()[1].bufnr))
   4385  au! BufRead Xtest2.txt
   4386 
   4387  " Test 2:
   4388  " When searching for a pattern using :vimgrep, if the quickfix list is
   4389  " freed, then a error should be given.
   4390  silent! %bwipe!
   4391  call setqflist([], 'f')
   4392  autocmd BufRead Xtest2.txt for i in range(10) | cexpr '' | endfor
   4393  call assert_fails('vimgrep stars Xtest*.txt', 'E925:')
   4394  au! BufRead Xtest2.txt
   4395 
   4396  " Test 3:
   4397  " When searching for a pattern using :lvimgrep, if the location list is
   4398  " freed, then the command should error out.
   4399  silent! %bwipe!
   4400  let g:save_winid = win_getid()
   4401  autocmd BufRead Xtest2.txt call setloclist(g:save_winid, [], 'f')
   4402  call assert_fails('lvimgrep stars Xtest*.txt', 'E926:')
   4403  au! BufRead Xtest2.txt
   4404  " cleanup the swap files
   4405  bw! Xtest2.txt Xtest1.txt
   4406 
   4407  call setqflist([], 'f')
   4408 endfunc
   4409 
   4410 " Test for an autocmd changing the current directory when running vimgrep
   4411 func Xvimgrep_autocmd_cd(cchar)
   4412  call s:setup_commands(a:cchar)
   4413 
   4414  %bwipe
   4415  let save_cwd = getcwd()
   4416 
   4417  augroup QF_Test
   4418    au!
   4419    autocmd BufRead * silent cd %:p:h
   4420  augroup END
   4421 
   4422  10Xvimgrep /vim/ Xdir/**
   4423  let l = g:Xgetlist()
   4424  call assert_equal('f1.txt', bufname(l[0].bufnr))
   4425  call assert_equal('f2.txt', fnamemodify(bufname(l[2].bufnr), ':t'))
   4426 
   4427  augroup QF_Test
   4428    au!
   4429  augroup END
   4430 
   4431  exe 'cd ' . save_cwd
   4432 endfunc
   4433 
   4434 func Test_vimgrep_autocmd_cd()
   4435  call mkdir('Xdir/a', 'p')
   4436  call mkdir('Xdir/b', 'p')
   4437  call writefile(['a_L1_vim', 'a_L2_vim'], 'Xdir/a/f1.txt')
   4438  call writefile(['b_L1_vim', 'b_L2_vim'], 'Xdir/b/f2.txt')
   4439  call Xvimgrep_autocmd_cd('c')
   4440  call Xvimgrep_autocmd_cd('l')
   4441  %bwipe
   4442  call delete('Xdir', 'rf')
   4443 endfunc
   4444 
   4445 " The following test used to crash Vim
   4446 func Test_lhelpgrep_autocmd()
   4447  lhelpgrep quickfix
   4448  augroup QF_Test
   4449    au!
   4450    autocmd QuickFixCmdPost * call setloclist(0, [], 'f')
   4451  augroup END
   4452  lhelpgrep buffer
   4453  call assert_equal('help', &filetype)
   4454  call assert_equal(0, getloclist(0, {'nr' : '$'}).nr)
   4455  lhelpgrep tabpage
   4456  call assert_equal('help', &filetype)
   4457  call assert_equal(1, getloclist(0, {'nr' : '$'}).nr)
   4458  augroup QF_Test
   4459    au!
   4460  augroup END
   4461 
   4462  new | only
   4463  augroup QF_Test
   4464    au!
   4465    au BufEnter * call setqflist([], 'f')
   4466  augroup END
   4467  call assert_fails('helpgrep quickfix', 'E925:')
   4468  " run the test with a help window already open
   4469  help
   4470  wincmd w
   4471  call assert_fails('helpgrep quickfix', 'E925:')
   4472  augroup QF_Test
   4473    au!
   4474  augroup END
   4475 
   4476  new | only
   4477  augroup QF_Test
   4478    au!
   4479    au BufEnter * call setqflist([], 'r')
   4480  augroup END
   4481  call assert_fails('helpgrep quickfix', 'E925:')
   4482  augroup QF_Test
   4483    au!
   4484  augroup END
   4485 
   4486  new | only
   4487  augroup QF_Test
   4488    au!
   4489    au BufEnter * call setloclist(0, [], 'r')
   4490  augroup END
   4491  call assert_fails('lhelpgrep quickfix', 'E926:')
   4492  augroup QF_Test
   4493    au!
   4494  augroup END
   4495 
   4496  " Replace the contents of a help window location list when it is still in
   4497  " use.
   4498  new | only
   4499  lhelpgrep quickfix
   4500  wincmd w
   4501  augroup QF_Test
   4502    au!
   4503    autocmd WinEnter * call setloclist(0, [], 'r')
   4504  augroup END
   4505  call assert_fails('lhelpgrep win_getid', 'E926:')
   4506  augroup QF_Test
   4507    au!
   4508  augroup END
   4509 
   4510  %bw!
   4511 endfunc
   4512 
   4513 " The following test used to crash Vim
   4514 func Test_lhelpgrep_autocmd_free_loclist()
   4515  %bw!
   4516  lhelpgrep quickfix
   4517  wincmd w
   4518  augroup QF_Test
   4519    au!
   4520    autocmd WinEnter * call setloclist(0, [], 'f')
   4521  augroup END
   4522  lhelpgrep win_getid
   4523  wincmd w
   4524  wincmd w
   4525  wincmd w
   4526  augroup QF_Test
   4527    au!
   4528  augroup END
   4529  %bw!
   4530 endfunc
   4531 
   4532 " Test for shortening/simplifying the file name when opening the
   4533 " quickfix window or when displaying the quickfix list
   4534 func Test_shorten_fname()
   4535  CheckUnix
   4536  %bwipe
   4537  " Create a quickfix list with an absolute path filename
   4538  let fname = getcwd() . '/test_quickfix.vim'
   4539  call setqflist([], ' ', {'lines':[fname . ":20:Line20"], 'efm':'%f:%l:%m'})
   4540  call assert_equal(fname, bufname('test_quickfix.vim'))
   4541  " Opening the quickfix window should simplify the file path
   4542  cwindow
   4543  call assert_equal('test_quickfix.vim', bufname('test_quickfix.vim'))
   4544  cclose
   4545  %bwipe
   4546  " Create a quickfix list with an absolute path filename
   4547  call setqflist([], ' ', {'lines':[fname . ":20:Line20"], 'efm':'%f:%l:%m'})
   4548  call assert_equal(fname, bufname('test_quickfix.vim'))
   4549  " Displaying the quickfix list should simplify the file path
   4550  silent! clist
   4551  call assert_equal('test_quickfix.vim', bufname('test_quickfix.vim'))
   4552  " Add a few entries for the same file with different paths and check whether
   4553  " the buffer name is shortened
   4554  %bwipe
   4555  call setqflist([], 'f')
   4556  call setqflist([{'filename' : 'test_quickfix.vim', 'lnum' : 10},
   4557        \ {'filename' : '../testdir/test_quickfix.vim', 'lnum' : 20},
   4558        \ {'filename' : fname, 'lnum' : 30}], ' ')
   4559  copen
   4560  call assert_equal(['test_quickfix.vim|10| ',
   4561        \ 'test_quickfix.vim|20| ',
   4562        \ 'test_quickfix.vim|30| '], getline(1, '$'))
   4563  cclose
   4564 endfunc
   4565 
   4566 " Quickfix title tests
   4567 " In the below tests, 'exe "cmd"' is used to invoke the quickfix commands.
   4568 " Otherwise due to indentation, the title is set with spaces at the beginning
   4569 " of the command.
   4570 func Test_qftitle()
   4571  call writefile(["F1:1:Line1"], 'Xerr')
   4572 
   4573  " :cexpr
   4574  exe "cexpr readfile('Xerr')"
   4575  call assert_equal(":cexpr readfile('Xerr')", getqflist({'title' : 1}).title)
   4576 
   4577  " :cgetexpr
   4578  exe "cgetexpr readfile('Xerr')"
   4579  call assert_equal(":cgetexpr readfile('Xerr')",
   4580 				\ getqflist({'title' : 1}).title)
   4581 
   4582  " :caddexpr
   4583  call setqflist([], 'f')
   4584  exe "caddexpr readfile('Xerr')"
   4585  call assert_equal(":caddexpr readfile('Xerr')",
   4586 				\ getqflist({'title' : 1}).title)
   4587 
   4588  " :cbuffer
   4589  new Xerr
   4590  exe "cbuffer"
   4591  call assert_equal(':cbuffer (Xerr)', getqflist({'title' : 1}).title)
   4592 
   4593  " :cgetbuffer
   4594  edit Xerr
   4595  exe "cgetbuffer"
   4596  call assert_equal(':cgetbuffer (Xerr)', getqflist({'title' : 1}).title)
   4597 
   4598  " :caddbuffer
   4599  call setqflist([], 'f')
   4600  edit Xerr
   4601  exe "caddbuffer"
   4602  call assert_equal(':caddbuffer (Xerr)', getqflist({'title' : 1}).title)
   4603 
   4604  " :cfile
   4605  exe "cfile Xerr"
   4606  call assert_equal(':cfile Xerr', getqflist({'title' : 1}).title)
   4607 
   4608  " :cgetfile
   4609  exe "cgetfile Xerr"
   4610  call assert_equal(':cgetfile Xerr', getqflist({'title' : 1}).title)
   4611 
   4612  " :caddfile
   4613  call setqflist([], 'f')
   4614  exe "caddfile Xerr"
   4615  call assert_equal(':caddfile Xerr', getqflist({'title' : 1}).title)
   4616 
   4617  " :grep
   4618  set grepprg=internal
   4619  exe "grep F1 Xerr"
   4620  call assert_equal(':grep F1 Xerr', getqflist({'title' : 1}).title)
   4621 
   4622  " :grepadd
   4623  call setqflist([], 'f')
   4624  exe "grepadd F1 Xerr"
   4625  call assert_equal(':grepadd F1 Xerr', getqflist({'title' : 1}).title)
   4626  set grepprg&vim
   4627 
   4628  " :vimgrep
   4629  exe "vimgrep F1 Xerr"
   4630  call assert_equal(':vimgrep F1 Xerr', getqflist({'title' : 1}).title)
   4631 
   4632  " :vimgrepadd
   4633  call setqflist([], 'f')
   4634  exe "vimgrepadd F1 Xerr"
   4635  call assert_equal(':vimgrepadd F1 Xerr', getqflist({'title' : 1}).title)
   4636 
   4637  call setqflist(['F1:10:L10'], ' ')
   4638  call assert_equal(':setqflist()', getqflist({'title' : 1}).title)
   4639 
   4640  call setqflist([], 'f')
   4641  call setqflist(['F1:10:L10'], 'a')
   4642  call assert_equal(':setqflist()', getqflist({'title' : 1}).title)
   4643 
   4644  call setqflist([], 'f')
   4645  call setqflist(['F1:10:L10'], 'r')
   4646  call assert_equal(':setqflist()', getqflist({'title' : 1}).title)
   4647 
   4648  close
   4649  call delete('Xerr')
   4650 
   4651  call setqflist([], ' ', {'title' : 'Errors'})
   4652  copen
   4653  call assert_equal('Errors', w:quickfix_title)
   4654  call setqflist([], 'r', {'items' : [{'filename' : 'a.c', 'lnum' : 10}]})
   4655  call assert_equal('Errors', w:quickfix_title)
   4656  cclose
   4657 
   4658  " Switching to another quickfix list in one tab page should update the
   4659  " quickfix window title and statusline in all the other tab pages also
   4660  call setqflist([], 'f')
   4661  %bw!
   4662  cgetexpr ['file_one:1:1: error in the first quickfix list']
   4663  call setqflist([], 'a', {'title': 'first quickfix list'})
   4664  cgetexpr ['file_two:2:1: error in the second quickfix list']
   4665  call setqflist([], 'a', {'title': 'second quickfix list'})
   4666  copen
   4667  wincmd t
   4668  tabnew two
   4669  copen
   4670  wincmd t
   4671  colder
   4672  call assert_equal('first quickfix list', gettabwinvar(1, 2, 'quickfix_title'))
   4673  call assert_equal('first quickfix list', gettabwinvar(2, 2, 'quickfix_title'))
   4674  call assert_equal(1, tabpagewinnr(1))
   4675  call assert_equal(1, tabpagewinnr(2))
   4676  tabnew
   4677  call setqflist([], 'a', {'title': 'new quickfix title'})
   4678  call assert_equal('new quickfix title', gettabwinvar(1, 2, 'quickfix_title'))
   4679  call assert_equal('new quickfix title', gettabwinvar(2, 2, 'quickfix_title'))
   4680  %bw!
   4681 endfunc
   4682 
   4683 func Test_lbuffer_with_bwipe()
   4684  new
   4685  new
   4686  augroup nasty
   4687    au QuickFixCmdPre,QuickFixCmdPost,BufEnter,BufLeave * bwipe
   4688  augroup END
   4689  lbuffer
   4690  augroup nasty
   4691    au!
   4692  augroup END
   4693 endfunc
   4694 
   4695 " Test for an autocmd freeing the quickfix/location list when cexpr/lexpr is
   4696 " running
   4697 func Xexpr_acmd_freelist(cchar)
   4698  call s:setup_commands(a:cchar)
   4699 
   4700  " This was using freed memory (but with what events?)
   4701  augroup nasty
   4702    au QuickFixCmdPre,QuickFixCmdPost,BufEnter,BufLeave * call g:Xsetlist([], 'f')
   4703  augroup END
   4704  Xexpr "x"
   4705  augroup nasty
   4706    au!
   4707  augroup END
   4708 endfunc
   4709 
   4710 func Test_cexpr_acmd_freelist()
   4711  call Xexpr_acmd_freelist('c')
   4712  call Xexpr_acmd_freelist('l')
   4713 endfunc
   4714 
   4715 " Test for commands that create a new quickfix/location list and jump to the
   4716 " first error automatically.
   4717 func Xjumpto_first_error_test(cchar)
   4718  call s:setup_commands(a:cchar)
   4719 
   4720  call s:create_test_file('Xtestfile1')
   4721  call s:create_test_file('Xtestfile2')
   4722  let l = ['Xtestfile1:2:Line2', 'Xtestfile2:4:Line4']
   4723 
   4724  " Test for cexpr/lexpr
   4725  enew
   4726  Xexpr l
   4727  call assert_equal('Xtestfile1', @%)
   4728  call assert_equal(2, line('.'))
   4729 
   4730  " Test for cfile/lfile
   4731  enew
   4732  call writefile(l, 'Xerr')
   4733  Xfile Xerr
   4734  call assert_equal('Xtestfile1', @%)
   4735  call assert_equal(2, line('.'))
   4736 
   4737  " Test for cbuffer/lbuffer
   4738  edit Xerr
   4739  Xbuffer
   4740  call assert_equal('Xtestfile1', @%)
   4741  call assert_equal(2, line('.'))
   4742 
   4743  call delete('Xerr')
   4744  call delete('Xtestfile1')
   4745  call delete('Xtestfile2')
   4746 endfunc
   4747 
   4748 func Test_jumpto_first_error()
   4749  call Xjumpto_first_error_test('c')
   4750  call Xjumpto_first_error_test('l')
   4751 endfunc
   4752 
   4753 " Test for a quickfix autocmd changing the quickfix/location list before
   4754 " jumping to the first error in the new list.
   4755 func Xautocmd_changelist(cchar)
   4756  call s:setup_commands(a:cchar)
   4757 
   4758  " Test for cfile/lfile
   4759  call s:create_test_file('Xtestfile1')
   4760  call s:create_test_file('Xtestfile2')
   4761  Xexpr 'Xtestfile1:2:Line2'
   4762  autocmd QuickFixCmdPost * Xolder
   4763  call writefile(['Xtestfile2:4:Line4'], 'Xerr')
   4764  Xfile Xerr
   4765  call assert_equal('Xtestfile2', @%)
   4766  call assert_equal(4, line('.'))
   4767  autocmd! QuickFixCmdPost
   4768 
   4769  " Test for cbuffer/lbuffer
   4770  call g:Xsetlist([], 'f')
   4771  Xexpr 'Xtestfile1:2:Line2'
   4772  autocmd QuickFixCmdPost * Xolder
   4773  call writefile(['Xtestfile2:4:Line4'], 'Xerr')
   4774  edit Xerr
   4775  Xbuffer
   4776  call assert_equal('Xtestfile2', @%)
   4777  call assert_equal(4, line('.'))
   4778  autocmd! QuickFixCmdPost
   4779 
   4780  " Test for cexpr/lexpr
   4781  call g:Xsetlist([], 'f')
   4782  Xexpr 'Xtestfile1:2:Line2'
   4783  autocmd QuickFixCmdPost * Xolder
   4784  Xexpr 'Xtestfile2:4:Line4'
   4785  call assert_equal('Xtestfile2', @%)
   4786  call assert_equal(4, line('.'))
   4787  autocmd! QuickFixCmdPost
   4788 
   4789  " The grepprg may not be set on non-Unix systems
   4790  if has('unix')
   4791    " Test for grep/lgrep
   4792    call g:Xsetlist([], 'f')
   4793    Xexpr 'Xtestfile1:2:Line2'
   4794    autocmd QuickFixCmdPost * Xolder
   4795    silent Xgrep Line5 Xtestfile2
   4796    call assert_equal('Xtestfile2', @%)
   4797    call assert_equal(5, line('.'))
   4798    autocmd! QuickFixCmdPost
   4799  endif
   4800 
   4801  " Test for vimgrep/lvimgrep
   4802  call g:Xsetlist([], 'f')
   4803  Xexpr 'Xtestfile1:2:Line2'
   4804  autocmd QuickFixCmdPost * Xolder
   4805  silent Xvimgrep Line5 Xtestfile2
   4806  call assert_equal('Xtestfile2', @%)
   4807  call assert_equal(5, line('.'))
   4808  autocmd! QuickFixCmdPost
   4809 
   4810  " Test for autocommands clearing the quickfix list before jumping to the
   4811  " first error. This should not result in an error
   4812  autocmd QuickFixCmdPost * call g:Xsetlist([], 'r')
   4813  let v:errmsg = ''
   4814  " Test for cfile/lfile
   4815  Xfile Xerr
   4816  call assert_true(v:errmsg !~# 'E42:')
   4817  " Test for cbuffer/lbuffer
   4818  edit Xerr
   4819  Xbuffer
   4820  call assert_true(v:errmsg !~# 'E42:')
   4821  " Test for cexpr/lexpr
   4822  Xexpr 'Xtestfile2:4:Line4'
   4823  call assert_true(v:errmsg !~# 'E42:')
   4824  " Test for grep/lgrep
   4825  " The grepprg may not be set on non-Unix systems
   4826  if has('unix')
   4827    silent Xgrep Line5 Xtestfile2
   4828    call assert_true(v:errmsg !~# 'E42:')
   4829  endif
   4830  " Test for vimgrep/lvimgrep
   4831  call assert_fails('silent Xvimgrep Line5 Xtestfile2', 'E480:')
   4832  autocmd! QuickFixCmdPost
   4833 
   4834  call delete('Xerr')
   4835  call delete('Xtestfile1')
   4836  call delete('Xtestfile2')
   4837 endfunc
   4838 
   4839 func Test_autocmd_changelist()
   4840  call Xautocmd_changelist('c')
   4841  call Xautocmd_changelist('l')
   4842 endfunc
   4843 
   4844 " Tests for the ':filter /pat/ clist' command
   4845 func Test_filter_clist()
   4846  cexpr ['Xfile1:10:10:Line 10', 'Xfile2:15:15:Line 15']
   4847  call assert_equal([' 2 Xfile2:15 col 15: Line 15'],
   4848 		\ split(execute('filter /Line 15/ clist'), "\n"))
   4849  call assert_equal([' 1 Xfile1:10 col 10: Line 10'],
   4850 		\ split(execute('filter /Xfile1/ clist'), "\n"))
   4851  call assert_equal([], split(execute('filter /abc/ clist'), "\n"))
   4852 
   4853  call setqflist([{'module' : 'abc', 'pattern' : 'pat1'},
   4854 		\ {'module' : 'pqr', 'pattern' : 'pat2'}], ' ')
   4855  call assert_equal([' 2 pqr:pat2:  '],
   4856 		\ split(execute('filter /pqr/ clist'), "\n"))
   4857  call assert_equal([' 1 abc:pat1:  '],
   4858 		\ split(execute('filter /pat1/ clist'), "\n"))
   4859 endfunc
   4860 
   4861 " Tests for the "CTRL-W <CR>" command.
   4862 func Xview_result_split_tests(cchar)
   4863  call s:setup_commands(a:cchar)
   4864 
   4865  " Test that "CTRL-W <CR>" in a qf/ll window fails with empty list.
   4866  call g:Xsetlist([])
   4867  Xopen
   4868  let l:win_count = winnr('$')
   4869  call assert_fails('execute "normal! \<C-W>\<CR>"', 'E42')
   4870  call assert_equal(l:win_count, winnr('$'))
   4871  Xclose
   4872 endfunc
   4873 
   4874 func Test_view_result_split()
   4875  call Xview_result_split_tests('c')
   4876  call Xview_result_split_tests('l')
   4877 endfunc
   4878 
   4879 " Test that :cc sets curswant
   4880 func Test_curswant()
   4881  helpgrep quickfix
   4882  normal! llll
   4883  1cc
   4884  call assert_equal(getcurpos()[4], virtcol('.'))
   4885  cclose | helpclose
   4886 endfunc
   4887 
   4888 " Test for opening a file from the quickfix window using CTRL-W <Enter>
   4889 " doesn't leave an empty buffer around.
   4890 func Test_splitview()
   4891  call s:create_test_file('Xtestfile1')
   4892  call s:create_test_file('Xtestfile2')
   4893  new | only
   4894  let last_bufnr = bufnr('Test_sv_1', 1)
   4895  let l = ['Xtestfile1:2:Line2', 'Xtestfile2:4:Line4']
   4896  cgetexpr l
   4897  copen
   4898  let numbufs = len(getbufinfo())
   4899  exe "normal \<C-W>\<CR>"
   4900  copen
   4901  exe "normal j\<C-W>\<CR>"
   4902  " Make sure new empty buffers are not created
   4903  call assert_equal(numbufs, len(getbufinfo()))
   4904  " Creating a new buffer should use the next available buffer number
   4905  call assert_equal(last_bufnr + 4, bufnr("Test_sv_2", 1))
   4906  bwipe Test_sv_1
   4907  bwipe Test_sv_2
   4908  new | only
   4909 
   4910  " When split opening files from location list window, make sure that two
   4911  " windows doesn't refer to the same location list
   4912  lgetexpr l
   4913  let locid = getloclist(0, {'id' : 0}).id
   4914  lopen
   4915  exe "normal \<C-W>\<CR>"
   4916  call assert_notequal(locid, getloclist(0, {'id' : 0}).id)
   4917  call assert_equal(0, getloclist(0, {'winid' : 0}).winid)
   4918  new | only
   4919 
   4920  " When split opening files from a helpgrep location list window, a new help
   4921  " window should be opened with a copy of the location list.
   4922  lhelpgrep window
   4923  let locid = getloclist(0, {'id' : 0}).id
   4924  lwindow
   4925  exe "normal j\<C-W>\<CR>"
   4926  call assert_notequal(locid, getloclist(0, {'id' : 0}).id)
   4927  call assert_equal(0, getloclist(0, {'winid' : 0}).winid)
   4928  new | only
   4929 
   4930  " Using :split or :vsplit from a quickfix window should behave like a :new
   4931  " or a :vnew command
   4932  copen
   4933  split
   4934  call assert_equal(3, winnr('$'))
   4935  let l = getwininfo()
   4936  call assert_equal([0, 0, 1], [l[0].quickfix, l[1].quickfix, l[2].quickfix])
   4937  close
   4938  copen
   4939  vsplit
   4940  let l = getwininfo()
   4941  call assert_equal([0, 0, 1], [l[0].quickfix, l[1].quickfix, l[2].quickfix])
   4942  new | only
   4943 
   4944  call delete('Xtestfile1')
   4945  call delete('Xtestfile2')
   4946 endfunc
   4947 
   4948 " Test for parsing entries using visual screen column
   4949 func Test_viscol()
   4950  enew
   4951  call writefile(["Col1\tCol2\tCol3"], 'Xfile1')
   4952  edit Xfile1
   4953 
   4954  " Use byte offset for column number
   4955  set efm&
   4956  cexpr "Xfile1:1:5:XX\nXfile1:1:9:YY\nXfile1:1:20:ZZ"
   4957  call assert_equal([5, 8], [col('.'), virtcol('.')])
   4958  cnext
   4959  call assert_equal([9, 12], [col('.'), virtcol('.')])
   4960  cnext
   4961  call assert_equal([14, 20], [col('.'), virtcol('.')])
   4962 
   4963  " Use screen column offset for column number
   4964  set efm=%f:%l:%v:%m
   4965  cexpr "Xfile1:1:8:XX\nXfile1:1:12:YY\nXfile1:1:20:ZZ"
   4966  call assert_equal([5, 8], [col('.'), virtcol('.')])
   4967  cnext
   4968  call assert_equal([9, 12], [col('.'), virtcol('.')])
   4969  cnext
   4970  call assert_equal([14, 20], [col('.'), virtcol('.')])
   4971  cexpr "Xfile1:1:6:XX\nXfile1:1:15:YY\nXfile1:1:24:ZZ"
   4972  call assert_equal([5, 8], [col('.'), virtcol('.')])
   4973  cnext
   4974  call assert_equal([10, 16], [col('.'), virtcol('.')])
   4975  cnext
   4976  call assert_equal([14, 20], [col('.'), virtcol('.')])
   4977 
   4978  enew
   4979  call writefile(["Col1\täü\töß\tCol4"], 'Xfile1')
   4980 
   4981  " Use byte offset for column number
   4982  set efm&
   4983  cexpr "Xfile1:1:8:XX\nXfile1:1:11:YY\nXfile1:1:16:ZZ"
   4984  call assert_equal([8, 10], [col('.'), virtcol('.')])
   4985  cnext
   4986  call assert_equal([11, 17], [col('.'), virtcol('.')])
   4987  cnext
   4988  call assert_equal([16, 25], [col('.'), virtcol('.')])
   4989 
   4990  " Use screen column offset for column number
   4991  set efm=%f:%l:%v:%m
   4992  cexpr "Xfile1:1:10:XX\nXfile1:1:17:YY\nXfile1:1:25:ZZ"
   4993  call assert_equal([8, 10], [col('.'), virtcol('.')])
   4994  cnext
   4995  call assert_equal([11, 17], [col('.'), virtcol('.')])
   4996  cnext
   4997  call assert_equal([16, 25], [col('.'), virtcol('.')])
   4998 
   4999  " Use screen column number with a multi-line error message
   5000  enew
   5001  call writefile(["à test"], 'Xfile1')
   5002  set efm=%E===\ %f\ ===,%C%l:%v,%Z%m
   5003  cexpr ["=== Xfile1 ===", "1:3", "errormsg"]
   5004  call assert_equal('Xfile1', @%)
   5005  call assert_equal([0, 1, 4, 0], getpos('.'))
   5006 
   5007  " Repeat previous test with byte offset %c: ensure that fix to issue #7145
   5008  " does not break this
   5009  set efm=%E===\ %f\ ===,%C%l:%c,%Z%m
   5010  cexpr ["=== Xfile1 ===", "1:3", "errormsg"]
   5011  call assert_equal('Xfile1', @%)
   5012  call assert_equal([0, 1, 3, 0], getpos('.'))
   5013 
   5014  enew | only
   5015  set efm&
   5016  call delete('Xfile1')
   5017 endfunc
   5018 
   5019 " Test for the quickfix window buffer
   5020 func Xqfbuf_test(cchar)
   5021  call s:setup_commands(a:cchar)
   5022 
   5023  " Quickfix buffer should be reused across closing and opening a quickfix
   5024  " window
   5025  Xexpr "F1:10:Line10"
   5026  Xopen
   5027  let qfbnum = bufnr('')
   5028  Xclose
   5029  " Even after the quickfix window is closed, the buffer should be loaded
   5030  call assert_true(bufloaded(qfbnum))
   5031  call assert_true(qfbnum, g:Xgetlist({'qfbufnr' : 0}).qfbufnr)
   5032  Xopen
   5033  " Buffer should be reused when opening the window again
   5034  call assert_equal(qfbnum, bufnr(''))
   5035  Xclose
   5036 
   5037  " When quickfix buffer is wiped out, getqflist() should return 0
   5038  %bw!
   5039  Xexpr ""
   5040  Xopen
   5041  bw!
   5042  call assert_equal(0, g:Xgetlist({'qfbufnr': 0}).qfbufnr)
   5043 
   5044  if a:cchar == 'l'
   5045    %bwipe
   5046    " For a location list, when both the file window and the location list
   5047    " window for the list are closed, then the buffer should be freed.
   5048    new | only
   5049    lexpr "F1:10:Line10"
   5050    let wid = win_getid()
   5051    lopen
   5052    let qfbnum = bufnr('')
   5053    call assert_match(qfbnum . ' %a-  "\[Location List]"', execute('ls'))
   5054    close
   5055    " When the location list window is closed, the buffer name should not
   5056    " change to 'Quickfix List'
   5057    call assert_match(qfbnum . 'u h-  "\[Location List]"', execute('ls!'))
   5058    call assert_true(bufloaded(qfbnum))
   5059 
   5060    " After deleting a location list buffer using ":bdelete", opening the
   5061    " location list window should mark the buffer as a location list buffer.
   5062    exe "bdelete " . qfbnum
   5063    lopen
   5064    call assert_equal("quickfix", &buftype)
   5065    call assert_equal(1, getwininfo(win_getid(winnr()))[0].loclist)
   5066    call assert_equal(wid, getloclist(0, {'filewinid' : 0}).filewinid)
   5067    call assert_false(&swapfile)
   5068    lclose
   5069 
   5070    " When the location list is cleared for the window, the buffer should be
   5071    " removed
   5072    call setloclist(0, [], 'f')
   5073    call assert_false(bufexists(qfbnum))
   5074    call assert_equal(0, getloclist(0, {'qfbufnr' : 0}).qfbufnr)
   5075 
   5076    " When the location list is freed with the location list window open, the
   5077    " location list buffer should not be lost. It should be reused when the
   5078    " location list is again populated.
   5079    lexpr "F1:10:Line10"
   5080    lopen
   5081    let wid = win_getid()
   5082    let qfbnum = bufnr('')
   5083    wincmd p
   5084    call setloclist(0, [], 'f')
   5085    lexpr "F1:10:Line10"
   5086    lopen
   5087    call assert_equal(wid, win_getid())
   5088    call assert_equal(qfbnum, bufnr(''))
   5089    lclose
   5090 
   5091    " When the window with the location list is closed, the buffer should be
   5092    " removed
   5093    new | only
   5094    call assert_false(bufexists(qfbnum))
   5095  endif
   5096 endfunc
   5097 
   5098 func Test_qfbuf()
   5099  call Xqfbuf_test('c')
   5100  call Xqfbuf_test('l')
   5101 endfunc
   5102 
   5103 " If there is an autocmd to use only one window, then opening the location
   5104 " list window used to crash Vim.
   5105 func Test_winonly_autocmd()
   5106  call s:create_test_file('Xtest1')
   5107  " Autocmd to show only one Vim window at a time
   5108  autocmd WinEnter * only
   5109  new
   5110  " Load the location list
   5111  lexpr "Xtest1:5:Line5\nXtest1:10:Line10\nXtest1:15:Line15"
   5112  let loclistid = getloclist(0, {'id' : 0}).id
   5113  " Open the location list window. Only this window will be shown and the file
   5114  " window is closed.
   5115  lopen
   5116  call assert_equal(loclistid, getloclist(0, {'id' : 0}).id)
   5117  " Jump to an entry in the location list and make sure that the cursor is
   5118  " positioned correctly.
   5119  ll 3
   5120  call assert_equal(loclistid, getloclist(0, {'id' : 0}).id)
   5121  call assert_equal('Xtest1', @%)
   5122  call assert_equal(15, line('.'))
   5123  " Cleanup
   5124  autocmd! WinEnter
   5125  new | only
   5126  call delete('Xtest1')
   5127 endfunc
   5128 
   5129 " Test to make sure that an empty quickfix buffer is not reused for loading
   5130 " a normal buffer.
   5131 func Test_empty_qfbuf()
   5132  enew | only
   5133  call writefile(["Test"], 'Xfile1')
   5134  call setqflist([], 'f')
   5135  copen | only
   5136  let qfbuf = bufnr('')
   5137  edit Xfile1
   5138  call assert_notequal(qfbuf, bufnr(''))
   5139  enew
   5140  call delete('Xfile1')
   5141 endfunc
   5142 
   5143 " Test for the :cbelow, :cabove, :lbelow and :labove commands.
   5144 " And for the :cafter, :cbefore, :lafter and :lbefore commands.
   5145 func Xtest_below(cchar)
   5146  call s:setup_commands(a:cchar)
   5147 
   5148  " No quickfix/location list
   5149  call assert_fails('Xbelow', 'E42:')
   5150  call assert_fails('Xabove', 'E42:')
   5151  call assert_fails('Xbefore', 'E42:')
   5152  call assert_fails('Xafter', 'E42:')
   5153 
   5154  " Empty quickfix/location list
   5155  call g:Xsetlist([])
   5156  call assert_fails('Xbelow', 'E42:')
   5157  call assert_fails('Xabove', 'E42:')
   5158  call assert_fails('Xbefore', 'E42:')
   5159  call assert_fails('Xafter', 'E42:')
   5160 
   5161  call s:create_test_file('X1')
   5162  call s:create_test_file('X2')
   5163  call s:create_test_file('X3')
   5164  call s:create_test_file('X4')
   5165 
   5166  " Invalid entries
   5167  edit X1
   5168  call g:Xsetlist(["E1", "E2"])
   5169  call assert_fails('Xbelow', 'E42:')
   5170  call assert_fails('Xabove', 'E42:')
   5171  call assert_fails('3Xbelow', 'E42:')
   5172  call assert_fails('4Xabove', 'E42:')
   5173  call assert_fails('Xbefore', 'E42:')
   5174  call assert_fails('Xafter', 'E42:')
   5175  call assert_fails('3Xbefore', 'E42:')
   5176  call assert_fails('4Xafter', 'E42:')
   5177 
   5178  " Test the commands with various arguments
   5179  Xexpr ["X1:5:3:L5", "X2:5:2:L5", "X2:10:3:L10", "X2:15:4:L15", "X3:3:5:L3"]
   5180  edit +7 X2
   5181  Xabove
   5182  call assert_equal(['X2', 5], [@%, line('.')])
   5183  call assert_fails('Xabove', 'E553:')
   5184  normal 7G
   5185  Xbefore
   5186  call assert_equal(['X2', 5, 2], [@%, line('.'), col('.')])
   5187  call assert_fails('Xbefore', 'E553:')
   5188 
   5189  normal 2j
   5190  Xbelow
   5191  call assert_equal(['X2', 10], [@%, line('.')])
   5192  normal 7G
   5193  Xafter
   5194  call assert_equal(['X2', 10, 3], [@%, line('.'), col('.')])
   5195 
   5196  " Last error in this file
   5197  Xbelow 99
   5198  call assert_equal(['X2', 15], [@%, line('.')])
   5199  call assert_fails('Xbelow', 'E553:')
   5200  normal gg
   5201  Xafter 99
   5202  call assert_equal(['X2', 15, 4], [@%, line('.'), col('.')])
   5203  call assert_fails('Xafter', 'E553:')
   5204 
   5205  " First error in this file
   5206  Xabove 99
   5207  call assert_equal(['X2', 5], [@%, line('.')])
   5208  call assert_fails('Xabove', 'E553:')
   5209  normal G
   5210  Xbefore 99
   5211  call assert_equal(['X2', 5, 2], [@%, line('.'), col('.')])
   5212  call assert_fails('Xbefore', 'E553:')
   5213 
   5214  normal gg
   5215  Xbelow 2
   5216  call assert_equal(['X2', 10], [@%, line('.')])
   5217  normal gg
   5218  Xafter 2
   5219  call assert_equal(['X2', 10, 3], [@%, line('.'), col('.')])
   5220 
   5221  normal G
   5222  Xabove 2
   5223  call assert_equal(['X2', 10], [@%, line('.')])
   5224  normal G
   5225  Xbefore 2
   5226  call assert_equal(['X2', 10, 3], [@%, line('.'), col('.')])
   5227 
   5228  edit X4
   5229  call assert_fails('Xabove', 'E42:')
   5230  call assert_fails('Xbelow', 'E42:')
   5231  call assert_fails('Xbefore', 'E42:')
   5232  call assert_fails('Xafter', 'E42:')
   5233  if a:cchar == 'l'
   5234    " If a buffer has location list entries from some other window but not
   5235    " from the current window, then the commands should fail.
   5236    edit X1 | split | call setloclist(0, [], 'f')
   5237    call assert_fails('Xabove', 'E776:')
   5238    call assert_fails('Xbelow', 'E776:')
   5239    call assert_fails('Xbefore', 'E776:')
   5240    call assert_fails('Xafter', 'E776:')
   5241    close
   5242  endif
   5243 
   5244  " Test for lines with multiple quickfix entries
   5245  let lines =<< trim END
   5246    X1:5:L5
   5247    X2:5:1:L5_1
   5248    X2:5:2:L5_2
   5249    X2:5:3:L5_3
   5250    X2:10:1:L10_1
   5251    X2:10:2:L10_2
   5252    X2:10:3:L10_3
   5253    X2:15:1:L15_1
   5254    X2:15:2:L15_2
   5255    X2:15:3:L15_3
   5256    X3:3:L3
   5257  END
   5258  Xexpr lines
   5259  edit +1 X2
   5260  Xbelow 2
   5261  call assert_equal(['X2', 10, 1], [@%, line('.'), col('.')])
   5262  normal 1G
   5263  Xafter 2
   5264  call assert_equal(['X2', 5, 2], [@%, line('.'), col('.')])
   5265 
   5266  normal gg
   5267  Xbelow 99
   5268  call assert_equal(['X2', 15, 1], [@%, line('.'), col('.')])
   5269  normal gg
   5270  Xafter 99
   5271  call assert_equal(['X2', 15, 3], [@%, line('.'), col('.')])
   5272 
   5273  normal G
   5274  Xabove 2
   5275  call assert_equal(['X2', 10, 1], [@%, line('.'), col('.')])
   5276  normal G
   5277  Xbefore 2
   5278  call assert_equal(['X2', 15, 2], [@%, line('.'), col('.')])
   5279 
   5280  normal G
   5281  Xabove 99
   5282  call assert_equal(['X2', 5, 1], [@%, line('.'), col('.')])
   5283  normal G
   5284  Xbefore 99
   5285  call assert_equal(['X2', 5, 1], [@%, line('.'), col('.')])
   5286 
   5287  normal 10G
   5288  Xabove
   5289  call assert_equal(['X2', 5, 1], [@%, line('.'), col('.')])
   5290  normal 10G$
   5291  2Xbefore
   5292  call assert_equal(['X2', 10, 2], [@%, line('.'), col('.')])
   5293 
   5294  normal 10G
   5295  Xbelow
   5296  call assert_equal(['X2', 15, 1], [@%, line('.'), col('.')])
   5297  normal 9G
   5298  5Xafter
   5299  call assert_equal(['X2', 15, 2], [@%, line('.'), col('.')])
   5300 
   5301  " Invalid range
   5302  if a:cchar == 'c'
   5303    call assert_fails('-2cbelow', 'E16:')
   5304    call assert_fails('-2cafter', 'E16:')
   5305  else
   5306    call assert_fails('-2lbelow', 'E16:')
   5307    call assert_fails('-2lafter', 'E16:')
   5308  endif
   5309 
   5310  call delete('X1')
   5311  call delete('X2')
   5312  call delete('X3')
   5313  call delete('X4')
   5314 endfunc
   5315 
   5316 func Test_cbelow()
   5317  call Xtest_below('c')
   5318  call Xtest_below('l')
   5319 endfunc
   5320 
   5321 func Test_quickfix_count()
   5322  let commands =<< trim END
   5323    cNext
   5324    cNfile
   5325    cabove
   5326    cbelow
   5327    cfirst
   5328    clast
   5329    cnewer
   5330    cnext
   5331    cnfile
   5332    colder
   5333    cprevious
   5334    crewind
   5335    lNext
   5336    lNfile
   5337    labove
   5338    lbelow
   5339    lfirst
   5340    llast
   5341    lnewer
   5342    lnext
   5343    lnfile
   5344    lolder
   5345    lprevious
   5346    lrewind
   5347  END
   5348  for cmd in commands
   5349    call assert_fails('-1' .. cmd, 'E16:')
   5350    call assert_fails('.' .. cmd, 'E16:')
   5351    call assert_fails('%' .. cmd, 'E16:')
   5352    call assert_fails('$' .. cmd, 'E16:')
   5353  endfor
   5354 endfunc
   5355 
   5356 " Test for aborting quickfix commands using QuickFixCmdPre
   5357 func Xtest_qfcmd_abort(cchar)
   5358  call s:setup_commands(a:cchar)
   5359 
   5360  call g:Xsetlist([], 'f')
   5361 
   5362  " cexpr/lexpr
   5363  let e = ''
   5364  try
   5365    Xexpr ["F1:10:Line10", "F2:20:Line20"]
   5366  catch /.*/
   5367    let e = v:exception
   5368  endtry
   5369  call assert_equal('AbortCmd', e)
   5370  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
   5371 
   5372  " cfile/lfile
   5373  call writefile(["F1:10:Line10", "F2:20:Line20"], 'Xfile1')
   5374  let e = ''
   5375  try
   5376    Xfile Xfile1
   5377  catch /.*/
   5378    let e = v:exception
   5379  endtry
   5380  call assert_equal('AbortCmd', e)
   5381  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
   5382  call delete('Xfile1')
   5383 
   5384  " cgetbuffer/lgetbuffer
   5385  enew!
   5386  call append(0, ["F1:10:Line10", "F2:20:Line20"])
   5387  let e = ''
   5388  try
   5389    Xgetbuffer
   5390  catch /.*/
   5391    let e = v:exception
   5392  endtry
   5393  call assert_equal('AbortCmd', e)
   5394  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
   5395  enew!
   5396 
   5397  " vimgrep/lvimgrep
   5398  let e = ''
   5399  try
   5400    Xvimgrep /func/ test_quickfix.vim
   5401  catch /.*/
   5402    let e = v:exception
   5403  endtry
   5404  call assert_equal('AbortCmd', e)
   5405  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
   5406 
   5407  " helpgrep/lhelpgrep
   5408  let e = ''
   5409  try
   5410    Xhelpgrep quickfix
   5411  catch /.*/
   5412    let e = v:exception
   5413  endtry
   5414  call assert_equal('AbortCmd', e)
   5415  call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
   5416 
   5417  " grep/lgrep
   5418  if has('unix')
   5419    let e = ''
   5420    try
   5421      silent Xgrep func test_quickfix.vim
   5422    catch /.*/
   5423      let e = v:exception
   5424    endtry
   5425    call assert_equal('AbortCmd', e)
   5426    call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
   5427  endif
   5428 endfunc
   5429 
   5430 func Test_qfcmd_abort()
   5431  augroup QF_Test
   5432    au!
   5433    autocmd  QuickFixCmdPre * throw "AbortCmd"
   5434  augroup END
   5435 
   5436  call Xtest_qfcmd_abort('c')
   5437  call Xtest_qfcmd_abort('l')
   5438 
   5439  augroup QF_Test
   5440    au!
   5441  augroup END
   5442 endfunc
   5443 
   5444 " Test for using a file in one of the parent directories.
   5445 func Test_search_in_dirstack()
   5446  call mkdir('Xtestdir/a/b/c', 'p')
   5447  let save_cwd = getcwd()
   5448  call writefile(["X1_L1", "X1_L2"], 'Xtestdir/Xfile1')
   5449  call writefile(["X2_L1", "X2_L2"], 'Xtestdir/a/Xfile2')
   5450  call writefile(["X3_L1", "X3_L2"], 'Xtestdir/a/b/Xfile3')
   5451  call writefile(["X4_L1", "X4_L2"], 'Xtestdir/a/b/c/Xfile4')
   5452 
   5453  let lines = "Entering dir Xtestdir\n" .
   5454       \ "Entering dir a\n" .
   5455       \ "Entering dir b\n" .
   5456       \ "Xfile2:2:X2_L2\n" .
   5457       \ "Leaving dir a\n" .
   5458       \ "Xfile1:2:X1_L2\n" .
   5459       \ "Xfile3:1:X3_L1\n" .
   5460       \ "Entering dir c\n" .
   5461       \ "Xfile4:2:X4_L2\n" .
   5462       \ "Leaving dir c\n"
   5463  set efm=%DEntering\ dir\ %f,%XLeaving\ dir\ %f,%f:%l:%m
   5464  cexpr lines .. "Leaving dir Xtestdir|\n" | let next = 1
   5465  call assert_equal(11, getqflist({'size' : 0}).size)
   5466  call assert_equal(4, getqflist({'idx' : 0}).idx)
   5467  call assert_equal('X2_L2', getline('.'))
   5468  call assert_equal(1, next)
   5469  cnext
   5470  call assert_equal(6, getqflist({'idx' : 0}).idx)
   5471  call assert_equal('X1_L2', getline('.'))
   5472  cnext
   5473  call assert_equal(7, getqflist({'idx' : 0}).idx)
   5474  call assert_equal(1, line('$'))
   5475  call assert_equal('', getline(1))
   5476  cnext
   5477  call assert_equal(9, getqflist({'idx' : 0}).idx)
   5478  call assert_equal(1, line('$'))
   5479  call assert_equal('', getline(1))
   5480 
   5481  set efm&
   5482  exe 'cd ' . save_cwd
   5483  call delete('Xtestdir', 'rf')
   5484 endfunc
   5485 
   5486 " Test for :cquit
   5487 func Test_cquit()
   5488  " Exit Vim with a non-zero value
   5489  if RunVim([], ["cquit 7"], '')
   5490    call assert_equal(7, v:shell_error)
   5491  endif
   5492 
   5493  if RunVim([], ["50cquit"], '')
   5494    call assert_equal(50, v:shell_error)
   5495  endif
   5496 
   5497  " Exit Vim with default value
   5498  if RunVim([], ["cquit"], '')
   5499    call assert_equal(1, v:shell_error)
   5500  endif
   5501 
   5502  " Exit Vim with zero value
   5503  if RunVim([], ["cquit 0"], '')
   5504    call assert_equal(0, v:shell_error)
   5505  endif
   5506 
   5507  " Exit Vim with negative value
   5508  call assert_fails('-3cquit', 'E16:')
   5509 endfunc
   5510 
   5511 " Test for getting a specific item from a quickfix list
   5512 func Xtest_getqflist_by_idx(cchar)
   5513  call s:setup_commands(a:cchar)
   5514  " Empty list
   5515  call assert_equal([], g:Xgetlist({'idx' : 1, 'items' : 0}).items)
   5516  Xexpr ['F1:10:L10', 'F1:20:L20']
   5517  let l = g:Xgetlist({'idx' : 2, 'items' : 0}).items
   5518  call assert_equal(bufnr('F1'), l[0].bufnr)
   5519  call assert_equal(20, l[0].lnum)
   5520  call assert_equal('L20', l[0].text)
   5521  call assert_equal([], g:Xgetlist({'idx' : -1, 'items' : 0}).items)
   5522  call assert_equal([], g:Xgetlist({'idx' : 3, 'items' : 0}).items)
   5523  call assert_equal({}, g:Xgetlist(#{idx: "abc"}))
   5524  %bwipe!
   5525 endfunc
   5526 
   5527 func Test_getqflist_by_idx()
   5528  call Xtest_getqflist_by_idx('c')
   5529  call Xtest_getqflist_by_idx('l')
   5530 endfunc
   5531 
   5532 " Test for the 'quickfixtextfunc' setting
   5533 func Tqfexpr(info)
   5534  if a:info.quickfix
   5535    let qfl = getqflist({'id' : a:info.id, 'items' : 1}).items
   5536  else
   5537    let qfl = getloclist(a:info.winid, {'id' : a:info.id, 'items' : 1}).items
   5538  endif
   5539 
   5540  let l = []
   5541  for idx in range(a:info.start_idx - 1, a:info.end_idx - 1)
   5542    let e = qfl[idx]
   5543    let s = ''
   5544    if e.bufnr != 0
   5545      let bname = bufname(e.bufnr)
   5546      let s ..= fnamemodify(bname, ':.')
   5547    endif
   5548    let s ..= '-'
   5549    let s ..= 'L' .. string(e.lnum) .. 'C' .. string(e.col) .. '-'
   5550    let s ..= e.text
   5551    call add(l, s)
   5552  endfor
   5553 
   5554  return l
   5555 endfunc
   5556 
   5557 func Xtest_qftextfunc(cchar)
   5558  call s:setup_commands(a:cchar)
   5559 
   5560  set efm=%f:%l:%c:%m
   5561  set quickfixtextfunc=Tqfexpr
   5562  call assert_equal('Tqfexpr', &quickfixtextfunc)
   5563  call assert_equal('',
   5564        \ g:Xgetlist({'quickfixtextfunc' : 1}).quickfixtextfunc)
   5565  call g:Xsetlist([
   5566        \ { 'filename': 'F1', 'lnum': 10, 'col': 2,
   5567        \   'end_col': 7, 'text': 'green'},
   5568        \ { 'filename': 'F1', 'lnum': 20, 'end_lnum': 25, 'col': 4,
   5569        \   'end_col': 8, 'text': 'blue'},
   5570        \ ])
   5571 
   5572  Xwindow
   5573  call assert_equal('F1-L10C2-green', getline(1))
   5574  call assert_equal('F1-L20C4-blue', getline(2))
   5575  Xclose
   5576  set quickfixtextfunc&vim
   5577  Xwindow
   5578  call assert_equal('F1|10 col 2-7| green', getline(1))
   5579  call assert_equal('F1|20-25 col 4-8| blue', getline(2))
   5580  Xclose
   5581 
   5582  set efm=%f:%l:%c:%m
   5583  set quickfixtextfunc=Tqfexpr
   5584  " Update the list with only the cwindow
   5585  Xwindow
   5586  only
   5587  call g:Xsetlist([
   5588        \ { 'filename': 'F2', 'lnum': 20, 'col': 2,
   5589        \   'end_col': 7, 'text': 'red'}
   5590        \ ])
   5591  call assert_equal(['F2-L20C2-red'], getline(1, '$'))
   5592  new
   5593  Xclose
   5594  set efm&
   5595  set quickfixtextfunc&
   5596 
   5597  " Test for per list 'quickfixtextfunc' setting
   5598  func PerQfText(info)
   5599    if a:info.quickfix
   5600      let qfl = getqflist({'id' : a:info.id, 'items' : 1}).items
   5601    else
   5602      let qfl = getloclist(a:info.winid, {'id' : a:info.id, 'items' : 1}).items
   5603    endif
   5604    if empty(qfl)
   5605      return []
   5606    endif
   5607    let l = []
   5608    for idx in range(a:info.start_idx - 1, a:info.end_idx - 1)
   5609      call add(l, 'Line ' .. qfl[idx].lnum .. ', Col ' .. qfl[idx].col)
   5610    endfor
   5611    return l
   5612  endfunc
   5613  set quickfixtextfunc=Tqfexpr
   5614  call g:Xsetlist([], ' ', {'quickfixtextfunc' : "PerQfText"})
   5615  Xaddexpr ['F1:10:2:green', 'F1:20:4:blue']
   5616  Xwindow
   5617  call assert_equal('Line 10, Col 2', getline(1))
   5618  call assert_equal('Line 20, Col 4', getline(2))
   5619  Xclose
   5620  call assert_equal(function('PerQfText'),
   5621        \ g:Xgetlist({'quickfixtextfunc' : 1}).quickfixtextfunc)
   5622  " Add entries to the list when the quickfix buffer is hidden
   5623  Xaddexpr ['F1:30:6:red']
   5624  Xwindow
   5625  call assert_equal('Line 30, Col 6', getline(3))
   5626  Xclose
   5627  call g:Xsetlist([], 'r', {'quickfixtextfunc' : ''})
   5628  call assert_equal('', g:Xgetlist({'quickfixtextfunc' : 1}).quickfixtextfunc)
   5629  set quickfixtextfunc&
   5630  delfunc PerQfText
   5631 
   5632  " Non-existing function
   5633  set quickfixtextfunc=Tabc
   5634  call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue']", 'E117:')
   5635  call assert_fails("Xwindow", 'E117:')
   5636  Xclose
   5637  set quickfixtextfunc&
   5638 
   5639  " set option to a non-function
   5640  set quickfixtextfunc=[10,\ 20]
   5641  call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue']", 'E117:')
   5642  call assert_fails("Xwindow", 'E117:')
   5643  Xclose
   5644  set quickfixtextfunc&
   5645 
   5646  " set option to a function with different set of arguments
   5647  func Xqftext(a, b, c)
   5648    return a:a .. a:b .. a:c
   5649  endfunc
   5650  set quickfixtextfunc=Xqftext
   5651  call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue']", 'E119:')
   5652  call assert_fails("Xwindow", 'E119:')
   5653  Xclose
   5654 
   5655  " set option to a function that returns a list with non-strings
   5656  func Xqftext2(d)
   5657    return ['one', [], 'two']
   5658  endfunc
   5659  set quickfixtextfunc=Xqftext2
   5660  call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue', 'F1:30:6:red']",
   5661                                                                  \ 'E730:')
   5662  call assert_fails('Xwindow', 'E730:')
   5663  call assert_equal(['one', 'F1|20 col 4| blue', 'F1|30 col 6| red'],
   5664        \ getline(1, '$'))
   5665  Xclose
   5666 
   5667  set quickfixtextfunc&
   5668  delfunc Xqftext
   5669  delfunc Xqftext2
   5670 
   5671  " set the global option to a lambda function
   5672  set quickfixtextfunc={d\ ->\ map(g:Xgetlist({'id'\ :\ d.id,\ 'items'\ :\ 1}).items[d.start_idx-1:d.end_idx-1],\ 'v:val.text')}
   5673  Xexpr ['F1:10:2:green', 'F1:20:4:blue']
   5674  Xwindow
   5675  call assert_equal(['green', 'blue'], getline(1, '$'))
   5676  Xclose
   5677  call assert_equal("{d -> map(g:Xgetlist({'id' : d.id, 'items' : 1}).items[d.start_idx-1:d.end_idx-1], 'v:val.text')}", &quickfixtextfunc)
   5678  set quickfixtextfunc&
   5679 
   5680  " use a lambda function that returns an empty list
   5681  set quickfixtextfunc={d\ ->\ []}
   5682  Xexpr ['F1:10:2:green', 'F1:20:4:blue']
   5683  Xwindow
   5684  call assert_equal(['F1|10 col 2| green', 'F1|20 col 4| blue'],
   5685        \ getline(1, '$'))
   5686  Xclose
   5687  set quickfixtextfunc&
   5688 
   5689  " use a lambda function that returns a list with empty strings
   5690  set quickfixtextfunc={d\ ->\ ['',\ '']}
   5691  Xexpr ['F1:10:2:green', 'F1:20:4:blue']
   5692  Xwindow
   5693  call assert_equal(['F1|10 col 2| green', 'F1|20 col 4| blue'],
   5694        \ getline(1, '$'))
   5695  Xclose
   5696  set quickfixtextfunc&
   5697 
   5698  " set the per-quickfix list text function to a lambda function
   5699  call g:Xsetlist([], ' ',
   5700        \ {'quickfixtextfunc' :
   5701        \   {d -> map(g:Xgetlist({'id' : d.id, 'items' : 1}).items[d.start_idx-1:d.end_idx-1],
   5702        \ "'Line ' .. v:val.lnum .. ', Col ' .. v:val.col")}})
   5703  Xaddexpr ['F1:10:2:green', 'F1:20:4:blue']
   5704  Xwindow
   5705  call assert_equal('Line 10, Col 2', getline(1))
   5706  call assert_equal('Line 20, Col 4', getline(2))
   5707  Xclose
   5708  call assert_match("function('<lambda>\\d\\+')", string(g:Xgetlist({'quickfixtextfunc' : 1}).quickfixtextfunc))
   5709  call g:Xsetlist([], 'f')
   5710 endfunc
   5711 
   5712 func Test_qftextfunc()
   5713  call Xtest_qftextfunc('c')
   5714  call Xtest_qftextfunc('l')
   5715 endfunc
   5716 
   5717 func Test_qftextfunc_callback()
   5718  let lines =<< trim END
   5719    set efm=%f:%l:%c:%m
   5720 
   5721    #" Test for using a function name
   5722    LET &qftf = 'g:Tqfexpr'
   5723    cexpr "F0:0:0:L0"
   5724    copen
   5725    call assert_equal('F0-L0C0-L0', getline(1))
   5726    cclose
   5727 
   5728    #" Test for using a function()
   5729    set qftf=function('g:Tqfexpr')
   5730    cexpr "F1:1:1:L1"
   5731    copen
   5732    call assert_equal('F1-L1C1-L1', getline(1))
   5733    cclose
   5734 
   5735    #" Using a funcref variable to set 'quickfixtextfunc'
   5736    VAR Fn = function('g:Tqfexpr')
   5737    LET &qftf = Fn
   5738    cexpr "F2:2:2:L2"
   5739    copen
   5740    call assert_equal('F2-L2C2-L2', getline(1))
   5741    cclose
   5742 
   5743    #" Using string(funcref_variable) to set 'quickfixtextfunc'
   5744    LET Fn = function('g:Tqfexpr')
   5745    LET &qftf = string(Fn)
   5746    cexpr "F3:3:3:L3"
   5747    copen
   5748    call assert_equal('F3-L3C3-L3', getline(1))
   5749    cclose
   5750 
   5751    #" Test for using a funcref()
   5752    set qftf=funcref('g:Tqfexpr')
   5753    cexpr "F4:4:4:L4"
   5754    copen
   5755    call assert_equal('F4-L4C4-L4', getline(1))
   5756    cclose
   5757 
   5758    #" Using a funcref variable to set 'quickfixtextfunc'
   5759    LET Fn = funcref('g:Tqfexpr')
   5760    LET &qftf = Fn
   5761    cexpr "F5:5:5:L5"
   5762    copen
   5763    call assert_equal('F5-L5C5-L5', getline(1))
   5764    cclose
   5765 
   5766    #" Using a string(funcref_variable) to set 'quickfixtextfunc'
   5767    LET Fn = funcref('g:Tqfexpr')
   5768    LET &qftf = string(Fn)
   5769    cexpr "F5:5:5:L5"
   5770    copen
   5771    call assert_equal('F5-L5C5-L5', getline(1))
   5772    cclose
   5773 
   5774    #" Test for using a lambda function with set
   5775    VAR optval = "LSTART a LMIDDLE Tqfexpr(a) LEND"
   5776    LET optval = substitute(optval, ' ', '\\ ', 'g')
   5777    exe "set qftf=" .. optval
   5778    cexpr "F6:6:6:L6"
   5779    copen
   5780    call assert_equal('F6-L6C6-L6', getline(1))
   5781    cclose
   5782 
   5783    #" Set 'quickfixtextfunc' to a lambda expression
   5784    LET &qftf = LSTART a LMIDDLE Tqfexpr(a) LEND
   5785    cexpr "F7:7:7:L7"
   5786    copen
   5787    call assert_equal('F7-L7C7-L7', getline(1))
   5788    cclose
   5789 
   5790    #" Set 'quickfixtextfunc' to string(lambda_expression)
   5791    LET &qftf = "LSTART a LMIDDLE Tqfexpr(a) LEND"
   5792    cexpr "F8:8:8:L8"
   5793    copen
   5794    call assert_equal('F8-L8C8-L8', getline(1))
   5795    cclose
   5796 
   5797    #" Set 'quickfixtextfunc' to a variable with a lambda expression
   5798    VAR Lambda = LSTART a LMIDDLE Tqfexpr(a) LEND
   5799    LET &qftf = Lambda
   5800    cexpr "F9:9:9:L9"
   5801    copen
   5802    call assert_equal('F9-L9C9-L9', getline(1))
   5803    cclose
   5804 
   5805    #" Set 'quickfixtextfunc' to a string(variable with a lambda expression)
   5806    LET Lambda = LSTART a LMIDDLE Tqfexpr(a) LEND
   5807    LET &qftf = string(Lambda)
   5808    cexpr "F9:9:9:L9"
   5809    copen
   5810    call assert_equal('F9-L9C9-L9', getline(1))
   5811    cclose
   5812  END
   5813  call CheckLegacyAndVim9Success(lines)
   5814 
   5815  " Test for using a script-local function name
   5816  func s:TqfFunc2(info)
   5817    let g:TqfFunc2Args = [a:info.start_idx, a:info.end_idx]
   5818    return ''
   5819  endfunc
   5820  let g:TqfFunc2Args = []
   5821  set quickfixtextfunc=s:TqfFunc2
   5822  cexpr "F10:10:10:L10"
   5823  cclose
   5824  call assert_equal([1, 1], g:TqfFunc2Args)
   5825 
   5826  let &quickfixtextfunc = 's:TqfFunc2'
   5827  cexpr "F11:11:11:L11"
   5828  cclose
   5829  call assert_equal([1, 1], g:TqfFunc2Args)
   5830  delfunc s:TqfFunc2
   5831 
   5832  " set 'quickfixtextfunc' to a partial with dict. This used to cause a crash.
   5833  func SetQftfFunc()
   5834    let params = {'qftf': function('g:DictQftfFunc')}
   5835    let &quickfixtextfunc = params.qftf
   5836  endfunc
   5837  func g:DictQftfFunc(_) dict
   5838  endfunc
   5839  call SetQftfFunc()
   5840  new
   5841  call SetQftfFunc()
   5842  bw
   5843  call test_garbagecollect_now()
   5844  new
   5845  set qftf=
   5846  wincmd w
   5847  set qftf=
   5848  :%bw!
   5849 
   5850  " set per-quickfix list 'quickfixtextfunc' to a partial with dict. This used
   5851  " to cause a crash.
   5852  let &qftf = ''
   5853  func SetLocalQftfFunc()
   5854    let params = {'qftf': function('g:DictQftfFunc')}
   5855    call setqflist([], 'a', {'quickfixtextfunc' : params.qftf})
   5856  endfunc
   5857  call SetLocalQftfFunc()
   5858  call test_garbagecollect_now()
   5859  call setqflist([], 'a', {'quickfixtextfunc' : ''})
   5860  delfunc g:DictQftfFunc
   5861  delfunc SetQftfFunc
   5862  delfunc SetLocalQftfFunc
   5863  set efm&
   5864 endfunc
   5865 
   5866 " Test for updating a location list for some other window and check that
   5867 " 'qftextfunc' uses the correct location list.
   5868 func Test_qftextfunc_other_loclist()
   5869  %bw!
   5870  call setloclist(0, [], 'f')
   5871 
   5872  " create a window and a location list for it and open the location list
   5873  " window
   5874  lexpr ['F1:10:12:one', 'F1:20:14:two']
   5875  let w1_id = win_getid()
   5876  call setloclist(0, [], ' ',
   5877        \ {'lines': ['F1:10:12:one', 'F1:20:14:two'],
   5878        \  'quickfixtextfunc':
   5879        \    {d -> map(getloclist(d.winid, {'id' : d.id,
   5880        \                'items' : 1}).items[d.start_idx-1:d.end_idx-1],
   5881        \          "'Line ' .. v:val.lnum .. ', Col ' .. v:val.col")}})
   5882  lwindow
   5883  let w2_id = win_getid()
   5884 
   5885  " create another window and a location list for it and open the location
   5886  " list window
   5887  topleft new
   5888  let w3_id = win_getid()
   5889  call setloclist(0, [], ' ',
   5890        \ {'lines': ['F2:30:32:eleven', 'F2:40:34:twelve'],
   5891        \  'quickfixtextfunc':
   5892        \    {d -> map(getloclist(d.winid, {'id' : d.id,
   5893        \                'items' : 1}).items[d.start_idx-1:d.end_idx-1],
   5894        \          "'Ligne ' .. v:val.lnum .. ', Colonne ' .. v:val.col")}})
   5895  lwindow
   5896  let w4_id = win_getid()
   5897 
   5898  topleft new
   5899  lexpr ['F3:50:52:green', 'F3:60:54:blue']
   5900  let w5_id = win_getid()
   5901 
   5902  " change the location list for some other window
   5903  call setloclist(0, [], 'r', {'lines': ['F3:55:56:aaa', 'F3:57:58:bbb']})
   5904  call setloclist(w1_id, [], 'r', {'lines': ['F1:62:63:bbb', 'F1:64:65:ccc']})
   5905  call setloclist(w3_id, [], 'r', {'lines': ['F2:76:77:ddd', 'F2:78:79:eee']})
   5906  call assert_equal(['Line 62, Col 63', 'Line 64, Col 65'],
   5907        \ getbufline(winbufnr(w2_id), 1, '$'))
   5908  call assert_equal(['Ligne 76, Colonne 77', 'Ligne 78, Colonne 79'],
   5909        \ getbufline(winbufnr(w4_id), 1, '$'))
   5910  call setloclist(w2_id, [], 'r', {'lines': ['F1:32:33:fff', 'F1:34:35:ggg']})
   5911  call setloclist(w4_id, [], 'r', {'lines': ['F2:46:47:hhh', 'F2:48:49:jjj']})
   5912  call assert_equal(['Line 32, Col 33', 'Line 34, Col 35'],
   5913        \ getbufline(winbufnr(w2_id), 1, '$'))
   5914  call assert_equal(['Ligne 46, Colonne 47', 'Ligne 48, Colonne 49'],
   5915        \ getbufline(winbufnr(w4_id), 1, '$'))
   5916 
   5917  call win_gotoid(w5_id)
   5918  lwindow
   5919  call assert_equal(['F3|55 col 56| aaa', 'F3|57 col 58| bbb'],
   5920        \ getline(1, '$'))
   5921  %bw!
   5922 endfunc
   5923 
   5924 " Running :lhelpgrep command more than once in a help window, doesn't jump to
   5925 " the help topic
   5926 func Test_lhelpgrep_from_help_window()
   5927  call mkdir('Xtestdir/doc', 'p')
   5928  call writefile(['window'], 'Xtestdir/doc/a.txt')
   5929  call writefile(['buffer'], 'Xtestdir/doc/b.txt')
   5930  let save_rtp = &rtp
   5931  let &rtp = 'Xtestdir'
   5932  lhelpgrep window
   5933  lhelpgrep buffer
   5934  call assert_equal('b.txt', fnamemodify(@%, ":p:t"))
   5935  lhelpgrep window
   5936  call assert_equal('a.txt', fnamemodify(@%, ":p:t"))
   5937  let &rtp = save_rtp
   5938  call delete('Xtestdir', 'rf')
   5939  new | only!
   5940 endfunc
   5941 
   5942 " Test for the crash fixed by 7.3.715
   5943 func Test_setloclist_crash()
   5944  %bw!
   5945  let g:BufNum = bufnr()
   5946  augroup QF_Test
   5947    au!
   5948    au BufUnload * call setloclist(0, [{'bufnr':g:BufNum, 'lnum':1, 'col':1, 'text': 'tango down'}])
   5949  augroup END
   5950 
   5951  try
   5952    lvimgrep /.*/ *.mak
   5953  catch /E926:/
   5954  endtry
   5955  call assert_equal('tango down', getloclist(0, {'items' : 0}).items[0].text)
   5956  call assert_equal(1, getloclist(0, {'size' : 0}).size)
   5957 
   5958  augroup QF_Test
   5959    au!
   5960  augroup END
   5961  unlet g:BufNum
   5962  %bw!
   5963 endfunc
   5964 
   5965 " Test for adding an invalid entry with the quickfix window open and making
   5966 " sure that the window contents are not changed
   5967 func Test_add_invalid_entry_with_qf_window()
   5968  call setqflist([], 'f')
   5969  cexpr "Xfile1:10:aa"
   5970  copen
   5971  call setqflist(['bb'], 'a')
   5972  call assert_equal(1, line('$'))
   5973  call assert_equal(['Xfile1|10| aa'], getline(1, '$'))
   5974  call assert_equal([{'lnum': 10                    , 'end_lnum': 0    , 'bufnr': bufnr('Xfile1') , 'col': 0   , 'end_col': 0    , 'pattern': '' , 'valid': 1 , 'vcol': 0 , 'nr': -1 , 'type': '' , 'module': '' , 'text': 'aa'}] , getqflist())
   5975 
   5976  call setqflist([{'lnum': 10                                          , 'bufnr': bufnr('Xfile1') , 'col': 0                     , 'pattern': '' , 'valid': 1 , 'vcol': 0 , 'nr': -1 , 'type': '' , 'module': '' , 'text': 'aa'}] , 'r')
   5977  call assert_equal(1                               , line('$'))
   5978  call assert_equal(['Xfile1|10| aa']               , getline(1        , '$'))
   5979  call assert_equal([{'lnum': 10                    , 'end_lnum': 0    , 'bufnr': bufnr('Xfile1') , 'col': 0   , 'end_col': 0    , 'pattern': '' , 'valid': 1 , 'vcol': 0 , 'nr': -1 , 'type': '' , 'module': '' , 'text': 'aa'}] , getqflist())
   5980 
   5981  call setqflist([{'lnum': 10                       , 'end_lnum': 0    , 'bufnr': bufnr('Xfile1') , 'col': 0   , 'end_col': 0    , 'pattern': '' , 'valid': 1 , 'vcol': 0 , 'nr': -1 , 'type': '' , 'module': '' , 'text': 'aa'}] , 'r')
   5982  call assert_equal(1                               , line('$'))
   5983  call assert_equal(['Xfile1|10| aa']               , getline(1        , '$'))
   5984  call assert_equal([{'lnum': 10                    , 'end_lnum': 0    , 'bufnr': bufnr('Xfile1') , 'col': 0   , 'end_col': 0    , 'pattern': '' , 'valid': 1 , 'vcol': 0 , 'nr': -1 , 'type': '' , 'module': '' , 'text': 'aa'}] , getqflist())
   5985 
   5986  call setqflist([{'lnum': 10                       , 'end_lnum': -123 , 'bufnr': bufnr('Xfile1') , 'col': 0   , 'end_col': -456 , 'pattern': '' , 'valid': 1 , 'vcol': 0 , 'nr': -1 , 'type': '' , 'module': '' , 'text': 'aa'}] , 'r')
   5987  call assert_equal(1                               , line('$'))
   5988  call assert_equal(['Xfile1|10| aa']               , getline(1        , '$'))
   5989  call assert_equal([{'lnum': 10                    , 'end_lnum': -123 , 'bufnr': bufnr('Xfile1') , 'col': 0   , 'end_col': -456 , 'pattern': '' , 'valid': 1 , 'vcol': 0 , 'nr': -1 , 'type': '' , 'module': '' , 'text': 'aa'}] , getqflist())
   5990 
   5991  call setqflist([{'lnum': 10                       , 'end_lnum': -123 , 'bufnr': bufnr('Xfile1') , 'col': 666 , 'end_col': 0    , 'pattern': '' , 'valid': 1 , 'vcol': 0 , 'nr': -1 , 'type': '' , 'module': '' , 'text': 'aa'}] , 'r')
   5992  call assert_equal(1                               , line('$'))
   5993  call assert_equal(['Xfile1|10 col 666| aa']       , getline(1        , '$'))
   5994  call assert_equal([{'lnum': 10                    , 'end_lnum': -123 , 'bufnr': bufnr('Xfile1') , 'col': 666 , 'end_col': 0    , 'pattern': '' , 'valid': 1 , 'vcol': 0 , 'nr': -1 , 'type': '' , 'module': '' , 'text': 'aa'}] , getqflist())
   5995 
   5996  call setqflist([{'lnum': 10                       , 'end_lnum': -123 , 'bufnr': bufnr('Xfile1') , 'col': 666 , 'end_col': -456 , 'pattern': '' , 'valid': 1 , 'vcol': 0 , 'nr': -1 , 'type': '' , 'module': '' , 'text': 'aa'}] , 'r')
   5997  call assert_equal(1                               , line('$'))
   5998  call assert_equal(['Xfile1|10 col 666| aa']       , getline(1        , '$'))
   5999  call assert_equal([{'lnum': 10                    , 'end_lnum': -123 , 'bufnr': bufnr('Xfile1') , 'col': 666 , 'end_col': -456 , 'pattern': '' , 'valid': 1 , 'vcol': 0 , 'nr': -1 , 'type': '' , 'module': '' , 'text': 'aa'}] , getqflist())
   6000 
   6001  call setqflist([{'lnum': 10                       , 'end_lnum': -123 , 'bufnr': bufnr('Xfile1') , 'col': 666 , 'end_col': 222  , 'pattern': '' , 'valid': 1 , 'vcol': 0 , 'nr': -1 , 'type': '' , 'module': '' , 'text': 'aa'}] , 'r')
   6002  call assert_equal(1                               , line('$'))
   6003  call assert_equal(['Xfile1|10 col 666-222| aa']   , getline(1        , '$'))
   6004  call assert_equal([{'lnum': 10                    , 'end_lnum': -123 , 'bufnr': bufnr('Xfile1') , 'col': 666 , 'end_col': 222  , 'pattern': '' , 'valid': 1 , 'vcol': 0 , 'nr': -1 , 'type': '' , 'module': '' , 'text': 'aa'}] , getqflist())
   6005 
   6006  call setqflist([{'lnum': 10                       , 'end_lnum': 6 , 'bufnr': bufnr('Xfile1') , 'col': 666 , 'end_col': 222  , 'pattern': '' , 'valid': 1 , 'vcol': 0 , 'nr': -1 , 'type': '' , 'module': '' , 'text': 'aa'}] , 'r')
   6007  call assert_equal(1                               , line('$'))
   6008  call assert_equal(['Xfile1|10-6 col 666-222| aa'] , getline(1        , '$'))
   6009  call assert_equal([{'lnum': 10                    , 'end_lnum': 6 , 'bufnr': bufnr('Xfile1') , 'col': 666 , 'end_col': 222  , 'pattern': '' , 'valid': 1 , 'vcol': 0 , 'nr': -1 , 'type': '' , 'module': '' , 'text': 'aa'}] , getqflist())
   6010  cclose
   6011 endfunc
   6012 
   6013 " Test for very weird problem: autocommand causes a failure, resulting opening
   6014 " the quickfix window to fail. This still splits the window, but otherwise
   6015 " should not mess up buffers.
   6016 func Test_quickfix_window_fails_to_open()
   6017  CheckScreendump
   6018 
   6019  let lines =<< trim END
   6020      anything
   6021      try
   6022        anything
   6023      endtry
   6024  END
   6025  call writefile(lines, 'XquickfixFails')
   6026 
   6027  let lines =<< trim END
   6028      split XquickfixFails
   6029      silent vimgrep anything %
   6030      normal o
   6031      au BufLeave * ++once source XquickfixFails
   6032      " This will trigger the autocommand, which causes an error, what follows
   6033      " is aborted but the window was already split.
   6034      silent! cwindow
   6035  END
   6036  call writefile(lines, 'XtestWinFails')
   6037  let buf = RunVimInTerminal('-S XtestWinFails', #{rows: 13})
   6038  call VerifyScreenDump(buf, 'Test_quickfix_window_fails', {})
   6039 
   6040  " clean up
   6041  call term_sendkeys(buf, ":bwipe!\<CR>")
   6042  call term_wait(buf)
   6043  call StopVimInTerminal(buf)
   6044  call delete('XtestWinFails')
   6045  call delete('XquickfixFails')
   6046 endfunc
   6047 
   6048 " Test for updating the quickfix buffer whenever the associated quickfix list
   6049 " is changed.
   6050 func Xqfbuf_update(cchar)
   6051  call s:setup_commands(a:cchar)
   6052 
   6053  Xexpr "F1:1:line1"
   6054  Xopen
   6055  call assert_equal(['F1|1| line1'], getline(1, '$'))
   6056  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
   6057 
   6058  " Test setqflist() using the 'lines' key in 'what'
   6059  " add a new entry
   6060  call g:Xsetlist([], 'a', {'lines' : ['F2:2: line2']})
   6061  call assert_equal(['F1|1| line1', 'F2|2| line2'], getline(1, '$'))
   6062  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
   6063  " replace all the entries with a single entry
   6064  call g:Xsetlist([], 'r', {'lines' : ['F3:3: line3']})
   6065  call assert_equal(['F3|3| line3'], getline(1, '$'))
   6066  call assert_equal(3, g:Xgetlist({'changedtick' : 0}).changedtick)
   6067  " remove all the entries
   6068  call g:Xsetlist([], 'r', {'lines' : []})
   6069  call assert_equal([''], getline(1, '$'))
   6070  call assert_equal(4, g:Xgetlist({'changedtick' : 0}).changedtick)
   6071  " add a new list
   6072  call g:Xsetlist([], ' ', {'lines' : ['F4:4: line4']})
   6073  call assert_equal(['F4|4| line4'], getline(1, '$'))
   6074  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
   6075 
   6076  " Test setqflist() using the 'items' key in 'what'
   6077  " add a new entry
   6078  call g:Xsetlist([], 'a', {'items' : [{'filename' : 'F5', 'lnum' : 5, 'text' : 'line5'}]})
   6079  call assert_equal(['F4|4| line4', 'F5|5| line5'], getline(1, '$'))
   6080  call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
   6081  " replace all the entries with a single entry
   6082  call g:Xsetlist([], 'r', {'items' : [{'filename' : 'F6', 'lnum' : 6, 'text' : 'line6'}]})
   6083  call assert_equal(['F6|6| line6'], getline(1, '$'))
   6084  call assert_equal(3, g:Xgetlist({'changedtick' : 0}).changedtick)
   6085  " remove all the entries
   6086  call g:Xsetlist([], 'r', {'items' : []})
   6087  call assert_equal([''], getline(1, '$'))
   6088  call assert_equal(4, g:Xgetlist({'changedtick' : 0}).changedtick)
   6089  " add a new list
   6090  call g:Xsetlist([], ' ', {'items' : [{'filename' : 'F7', 'lnum' : 7, 'text' : 'line7'}]})
   6091  call assert_equal(['F7|7| line7'], getline(1, '$'))
   6092  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
   6093 
   6094  call g:Xsetlist([], ' ', {})
   6095  call assert_equal([''], getline(1, '$'))
   6096  call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
   6097 
   6098  Xclose
   6099 endfunc
   6100 
   6101 func Test_qfbuf_update()
   6102  call Xqfbuf_update('c')
   6103  call Xqfbuf_update('l')
   6104 endfunc
   6105 
   6106 func Test_vimgrep_noswapfile()
   6107  set noswapfile
   6108  call writefile(['one', 'two', 'three'], 'Xgreppie')
   6109  vimgrep two Xgreppie
   6110  call assert_equal('two', getline('.'))
   6111 
   6112  call delete('Xgreppie')
   6113  set swapfile
   6114 endfunc
   6115 
   6116 " Test for the :vimgrep 'f' flag (fuzzy match)
   6117 func Xvimgrep_fuzzy_match(cchar)
   6118  call s:setup_commands(a:cchar)
   6119 
   6120  Xvimgrep /three one/f Xfile*
   6121  let l = g:Xgetlist()
   6122  call assert_equal(2, len(l))
   6123  call assert_equal(['Xfile1', 1, 9, 'one two three'],
   6124        \ [bufname(l[0].bufnr), l[0].lnum, l[0].col, l[0].text])
   6125  call assert_equal(['Xfile2', 2, 1, 'three one two'],
   6126        \ [bufname(l[1].bufnr), l[1].lnum, l[1].col, l[1].text])
   6127 
   6128  Xvimgrep /the/f Xfile*
   6129  let l = g:Xgetlist()
   6130  call assert_equal(3, len(l))
   6131  call assert_equal(['Xfile1', 1, 9, 'one two three'],
   6132        \ [bufname(l[0].bufnr), l[0].lnum, l[0].col, l[0].text])
   6133  call assert_equal(['Xfile2', 2, 1, 'three one two'],
   6134        \ [bufname(l[1].bufnr), l[1].lnum, l[1].col, l[1].text])
   6135  call assert_equal(['Xfile2', 4, 4, 'aaathreeaaa'],
   6136        \ [bufname(l[2].bufnr), l[2].lnum, l[2].col, l[2].text])
   6137 
   6138  Xvimgrep /aaa/fg Xfile*
   6139  let l = g:Xgetlist()
   6140  call assert_equal(4, len(l))
   6141  call assert_equal(['Xfile1', 2, 1, 'aaaaaa'],
   6142        \ [bufname(l[0].bufnr), l[0].lnum, l[0].col, l[0].text])
   6143  call assert_equal(['Xfile1', 2, 4, 'aaaaaa'],
   6144        \ [bufname(l[1].bufnr), l[1].lnum, l[1].col, l[1].text])
   6145  call assert_equal(['Xfile2', 4, 1, 'aaathreeaaa'],
   6146        \ [bufname(l[2].bufnr), l[2].lnum, l[2].col, l[2].text])
   6147  call assert_equal(['Xfile2', 4, 9, 'aaathreeaaa'],
   6148        \ [bufname(l[3].bufnr), l[3].lnum, l[3].col, l[3].text])
   6149 
   6150  call assert_fails('Xvimgrep /xyz/fg Xfile*', 'E480:')
   6151 endfunc
   6152 
   6153 func Test_vimgrep_fuzzy_match()
   6154  call writefile(['one two three', 'aaaaaa'], 'Xfile1')
   6155  call writefile(['one', 'three one two', 'two', 'aaathreeaaa'], 'Xfile2')
   6156  call Xvimgrep_fuzzy_match('c')
   6157  call Xvimgrep_fuzzy_match('l')
   6158  call delete('Xfile1')
   6159  call delete('Xfile2')
   6160 endfunc
   6161 
   6162 func Test_locationlist_open_in_newtab()
   6163  call s:create_test_file('Xqftestfile1')
   6164  call s:create_test_file('Xqftestfile2')
   6165  call s:create_test_file('Xqftestfile3')
   6166 
   6167  %bwipe!
   6168 
   6169  let lines =<< trim END
   6170    Xqftestfile1:5:Line5
   6171    Xqftestfile2:10:Line10
   6172    Xqftestfile3:16:Line16
   6173  END
   6174  lgetexpr lines
   6175 
   6176  silent! llast
   6177  call assert_equal(1, tabpagenr('$'))
   6178  call assert_equal('Xqftestfile3', bufname())
   6179 
   6180  set switchbuf=newtab
   6181 
   6182  silent! lfirst
   6183  call assert_equal(2, tabpagenr('$'))
   6184  call assert_equal('Xqftestfile1', bufname())
   6185 
   6186  silent! lnext
   6187  call assert_equal(3, tabpagenr('$'))
   6188  call assert_equal('Xqftestfile2', bufname())
   6189 
   6190  call delete('Xqftestfile1')
   6191  call delete('Xqftestfile2')
   6192  call delete('Xqftestfile3')
   6193  set switchbuf&vim
   6194 
   6195  %bwipe!
   6196 endfunc
   6197 
   6198 " Test for win_gettype() in quickfix and location list windows
   6199 func Test_win_gettype()
   6200  copen
   6201  call assert_equal("quickfix", win_gettype())
   6202  let wid = win_getid()
   6203  wincmd p
   6204  call assert_equal("quickfix", win_gettype(wid))
   6205  cclose
   6206  lexpr ''
   6207  lopen
   6208  call assert_equal("loclist", win_gettype())
   6209  let wid = win_getid()
   6210  wincmd p
   6211  call assert_equal("loclist", win_gettype(wid))
   6212  lclose
   6213 endfunc
   6214 
   6215 fun Test_vimgrep_nomatch()
   6216  call XexprTests('c')
   6217  call g:Xsetlist([{'lnum':10,'text':'Line1'}])
   6218  copen
   6219  if has("win32")
   6220    call assert_fails('vimgrep foo *.zzz', 'E479:')
   6221    let expected = [{'lnum': 10, 'bufnr': 0, 'end_lnum': 0, 'pattern': '', 'valid': 0, 'vcol': 0, 'nr': 0, 'module': '', 'type': '', 'end_col': 0, 'col': 0, 'text': 'Line1'}]
   6222  else
   6223    call assert_fails('vimgrep foo *.zzz', 'E480:')
   6224    let expected = []
   6225  endif
   6226  call assert_equal(expected, getqflist())
   6227  cclose
   6228 endfunc
   6229 
   6230 " Test for opening the quickfix window in two tab pages and then closing one
   6231 " of the quickfix windows. This should not make the quickfix buffer unlisted.
   6232 " (github issue #9300).
   6233 func Test_two_qf_windows()
   6234  cexpr "F1:1:line1"
   6235  copen
   6236  tabnew
   6237  copen
   6238  call assert_true(&buflisted)
   6239  cclose
   6240  tabfirst
   6241  call assert_true(&buflisted)
   6242  let bnum = bufnr()
   6243  cclose
   6244  " if all the quickfix windows are closed, then buffer should be unlisted.
   6245  call assert_false(buflisted(bnum))
   6246  %bw!
   6247 
   6248  " Repeat the test for a location list
   6249  lexpr "F2:2:line2"
   6250  lopen
   6251  let bnum = bufnr()
   6252  tabnew
   6253  exe "buffer" bnum
   6254  tabfirst
   6255  lclose
   6256  tablast
   6257  call assert_true(buflisted(bnum))
   6258  tabclose
   6259  lopen
   6260  call assert_true(buflisted(bnum))
   6261  lclose
   6262  call assert_false(buflisted(bnum))
   6263  %bw!
   6264 endfunc
   6265 
   6266 " Weird sequence of commands that caused entering a wiped-out buffer
   6267 func Test_lopen_bwipe()
   6268  func R()
   6269    silent! tab lopen
   6270    e x
   6271    silent! lfile
   6272  endfunc
   6273 
   6274  cal R()
   6275  cal R()
   6276  cal R()
   6277  bw!
   6278  delfunc R
   6279 endfunc
   6280 
   6281 " Another sequence of commands that caused all buffers to be wiped out
   6282 func Test_lopen_bwipe_all()
   6283  let lines =<< trim END
   6284    func R()
   6285      silent! tab lopen
   6286      e foo
   6287      silent! lfile
   6288    endfunc
   6289    cal R()
   6290    exe "norm \<C-W>\<C-V>0"
   6291    cal R()
   6292    bwipe
   6293 
   6294    call writefile(['done'], 'Xresult')
   6295    qall!
   6296  END
   6297  call writefile(lines, 'Xscript')
   6298  if RunVim([], [], '-u NONE -n -X -Z -e -m -s -S Xscript')
   6299    call assert_equal(['done'], readfile('Xresult'))
   6300  endif
   6301 
   6302  call delete('Xscript')
   6303  call delete('Xresult')
   6304 endfunc
   6305 
   6306 " Test for calling setqflist() function recursively
   6307 func Test_recursive_setqflist()
   6308  augroup QF_Test
   6309    au!
   6310    autocmd BufWinEnter quickfix call setqflist([], 'r')
   6311  augroup END
   6312 
   6313  copen
   6314  call assert_fails("call setqflist([], 'a')", 'E952:')
   6315 
   6316  augroup QF_Test
   6317    au!
   6318  augroup END
   6319  %bw!
   6320 endfunc
   6321 
   6322 " Test for failure to create a new window when selecting a file from the
   6323 " quickfix window
   6324 func Test_cwindow_newwin_fails()
   6325  cgetexpr ["Xfile1:10:L10", "Xfile1:20:L20"]
   6326  cwindow
   6327  only
   6328  let qf_wid = win_getid()
   6329  " create the maximum number of scratch windows
   6330  let hor_win_count = (&lines - 1)/2
   6331  let hor_split_count = hor_win_count - 1
   6332  for s in range(1, hor_split_count) | new | set buftype=nofile | endfor
   6333  call win_gotoid(qf_wid)
   6334  call assert_fails('exe "normal \<CR>"', 'E36:')
   6335  %bw!
   6336 endfunc
   6337 
   6338 " Test for updating the location list when only the location list window is
   6339 " present and the corresponding file window is closed.
   6340 func Test_loclist_update_with_llwin_only()
   6341  %bw!
   6342  new
   6343  wincmd w
   6344  lexpr ["Xfile1:1:Line1"]
   6345  lopen
   6346  wincmd p
   6347  close
   6348  call setloclist(2, [], 'r', {'lines': ["Xtest2:2:Line2"]})
   6349  call assert_equal(['Xtest2|2| Line2'], getbufline(winbufnr(2), 1, '$'))
   6350  %bw!
   6351 endfunc
   6352 
   6353 " Test for getting the quickfix list after a buffer with an error is wiped out
   6354 func Test_getqflist_wiped_out_buffer()
   6355  %bw!
   6356  cexpr ["Xtest1:34:Wiped out"]
   6357  let bnum = bufnr('Xtest1')
   6358  call assert_equal(bnum, getqflist()[0].bufnr)
   6359  bw Xtest1
   6360  call assert_equal(0, getqflist()[0].bufnr)
   6361  %bw!
   6362 endfunc
   6363 
   6364 " Test for the status message that is displayed when opening a new quickfix
   6365 " list
   6366 func Test_qflist_statusmsg()
   6367  cexpr "1\n2"
   6368  cexpr "1\n2\n3\ntest_quickfix.vim:1:msg"
   6369  call assert_equal('(4 of 4): msg', v:statusmsg)
   6370  call setqflist([], 'f')
   6371  %bw!
   6372 
   6373  " When creating a new quickfix list, if an autocmd changes the quickfix list
   6374  " in the stack, then an error message should be displayed.
   6375  augroup QF_Test
   6376    au!
   6377    au BufEnter test_quickfix.vim colder
   6378  augroup END
   6379  cexpr "1\n2"
   6380  call assert_fails('cexpr "1\n2\n3\ntest_quickfix.vim:1:msg"', 'E925:')
   6381  call setqflist([], 'f')
   6382  augroup QF_Test
   6383    au!
   6384  augroup END
   6385  %bw!
   6386 
   6387  augroup QF_Test
   6388    au!
   6389    au BufEnter test_quickfix.vim caddexpr "4"
   6390  augroup END
   6391  call assert_fails('cexpr "1\n2\n3\ntest_quickfix.vim:1:msg"', 'E925:')
   6392  call setqflist([], 'f')
   6393  augroup QF_Test
   6394    au!
   6395  augroup END
   6396  %bw!
   6397 endfunc
   6398 
   6399 func Test_quickfixtextfunc_recursive()
   6400  func s:QFTfunc(o)
   6401    cgete '0'
   6402  endfunc
   6403  copen
   6404  let &quickfixtextfunc = 's:QFTfunc'
   6405  cex ""
   6406 
   6407  let &quickfixtextfunc = ''
   6408  cclose
   6409 endfunc
   6410 
   6411 " Test for replacing the location list from an autocmd. This used to cause a
   6412 " read from freed memory.
   6413 func Test_loclist_replace_autocmd()
   6414  %bw!
   6415  call setloclist(0, [], 'f')
   6416  let s:bufnr = bufnr()
   6417  cal setloclist(0, [{'0': 0, '': ''}])
   6418  au BufEnter * cal setloclist(1, [{'t': ''}, {'bufnr': s:bufnr}], 'r')
   6419  lopen
   6420  try
   6421    exe "norm j\<CR>"
   6422  catch
   6423  endtry
   6424  lnext
   6425  %bw!
   6426  call setloclist(0, [], 'f')
   6427 endfunc
   6428 
   6429 " Test for a very long error line and a very long information line
   6430 func Test_very_long_error_line()
   6431  let msg = repeat('abcdefghijklmn', 146)
   6432  let emsg = 'Xlonglines.c:1:' . msg
   6433  call writefile([msg, emsg], 'Xerror', 'D')
   6434  cfile Xerror
   6435  cwindow
   6436  call assert_equal($'|| {msg}', getline(1))
   6437  call assert_equal($'Xlonglines.c|1| {msg}', getline(2))
   6438  cclose
   6439 
   6440  let l = execute('clist!')->split("\n")
   6441  call assert_equal([$' 1: {msg}', $' 2 Xlonglines.c:1: {msg}'], l)
   6442 
   6443  let l = execute('cc')->split("\n")
   6444  call assert_equal([$'(2 of 2): {msg}'], l)
   6445 
   6446  call setqflist([], 'f')
   6447 endfunc
   6448 
   6449 " In the quickfix window, spaces at the beginning of an informational line
   6450 " should not be removed but should be removed from an error line.
   6451 func Test_info_line_with_space()
   6452  cexpr ["a.c:20:12:         error: expected ';' before ':' token",
   6453        \ '   20 |     Afunc():', '', '      |            ^']
   6454  copen
   6455  call assert_equal(["a.c|20 col 12| error: expected ';' before ':' token",
   6456        \ '||    20 |     Afunc():', '|| ',
   6457        \ '||       |            ^'], getline(1, '$'))
   6458  cclose
   6459 
   6460  let l = execute('clist!')->split("\n")
   6461  call assert_equal([" 1 a.c:20 col 12: error: expected ';' before ':' token",
   6462        \ ' 2:    20 |     Afunc():', ' 3:  ', ' 4:       |            ^'], l)
   6463 
   6464  call setqflist([], 'f')
   6465 endfunc
   6466 
   6467 func s:QfTf(_)
   6468 endfunc
   6469 
   6470 func Test_setqflist_cb_arg()
   6471  " This was changing the callback name in the dictionary.
   6472  let d = #{quickfixtextfunc: 's:QfTf'}
   6473  call setqflist([], 'a', d)
   6474  call assert_equal('s:QfTf', d.quickfixtextfunc)
   6475 
   6476  call setqflist([], 'f')
   6477 endfunc
   6478 
   6479 " Test that setqflist() should not prevent :stopinsert from working
   6480 func Test_setqflist_stopinsert()
   6481  new
   6482  call setqflist([], 'f')
   6483  copen
   6484  cclose
   6485  func StopInsert()
   6486    stopinsert
   6487    call setqflist([{'text': 'foo'}])
   6488    return ''
   6489  endfunc
   6490 
   6491  call setline(1, 'abc')
   6492  call cursor(1, 1)
   6493  call feedkeys("i\<C-R>=StopInsert()\<CR>$", 'tnix')
   6494  call assert_equal('foo', getqflist()[0].text)
   6495  call assert_equal([0, 1, 3, 0, v:maxcol], getcurpos())
   6496  call assert_equal(['abc'], getline(1, '$'))
   6497 
   6498  delfunc StopInsert
   6499  call setqflist([], 'f')
   6500  bwipe!
   6501 endfunc
   6502 
   6503 func Test_quickfix_buffer_contents()
   6504  call setqflist([{'filename':'filename', 'pattern':'pattern', 'text':'text'}])
   6505  copen
   6506  call assert_equal(['filename|pattern| text'], getline(1, '$'))  " The assert failed with Vim v9.0.0736; '| text' did not appear after the pattern.
   6507  call setqflist([], 'f')
   6508 endfunc
   6509 
   6510 func XquickfixUpdateTests(cchar)
   6511  call s:setup_commands(a:cchar)
   6512 
   6513  " Setup: populate a couple buffers
   6514  new
   6515  call setline(1, range(1, 5))
   6516  let b1 = bufnr()
   6517  new
   6518  call setline(1, range(1, 3))
   6519  let b2 = bufnr()
   6520  " Setup: set a quickfix list.
   6521  let items = [{'bufnr': b1, 'lnum': 1}, {'bufnr': b1, 'lnum': 2}, {'bufnr': b2, 'lnum': 1}, {'bufnr': b2, 'lnum': 2}]
   6522  call g:Xsetlist(items)
   6523 
   6524  " Open the quickfix list, select the third entry.
   6525  Xopen
   6526  exe "normal jj\<CR>"
   6527  call assert_equal(3, g:Xgetlist({'idx' : 0}).idx)
   6528 
   6529  " Update the quickfix list. Make sure the third entry is still selected.
   6530  call g:Xsetlist([], 'u', { 'items': items })
   6531  call assert_equal(3, g:Xgetlist({'idx' : 0}).idx)
   6532 
   6533  " Update the quickfix list again, but this time with missing line number
   6534  " information. Confirm that we keep the current buffer selected.
   6535  call g:Xsetlist([{'bufnr': b1}, {'bufnr': b2}], 'u')
   6536  call assert_equal(2, g:Xgetlist({'idx' : 0}).idx)
   6537 
   6538  Xclose
   6539 
   6540  " Cleanup the buffers we allocated during this test.
   6541  %bwipe!
   6542 endfunc
   6543 
   6544 " Test for updating a quickfix list using the "u" flag in setqflist()
   6545 func Test_quickfix_update()
   6546  call XquickfixUpdateTests('c')
   6547  call XquickfixUpdateTests('l')
   6548 endfunc
   6549 
   6550 func Test_quickfix_update_with_missing_coordinate_info()
   6551  new
   6552  call setline(1, range(1, 5))
   6553  let b1 = bufnr()
   6554 
   6555  new
   6556  call setline(1, range(1, 3))
   6557  let b2 = bufnr()
   6558 
   6559  new
   6560  call setline(1, range(1, 2))
   6561  let b3 = bufnr()
   6562 
   6563  " Setup: set a quickfix list with no coordinate information at all.
   6564  call setqflist([{}, {}])
   6565 
   6566  " Open the quickfix list, select the second entry.
   6567  copen
   6568  exe "normal j\<CR>"
   6569  call assert_equal(2, getqflist({'idx' : 0}).idx)
   6570 
   6571  " Update the quickfix list. As the previously selected entry has no
   6572  " coordinate information, we expect the first entry to now be selected.
   6573  call setqflist([{'bufnr': b1}, {'bufnr': b2}, {'bufnr': b3}], 'u')
   6574  call assert_equal(1, getqflist({'idx' : 0}).idx)
   6575 
   6576  " Select the second entry in the quickfix list.
   6577  copen
   6578  exe "normal j\<CR>"
   6579  call assert_equal(2, getqflist({'idx' : 0}).idx)
   6580 
   6581  " Update the quickfix list again. The currently selected entry does not have
   6582  " a line number, but we should keep the file selected.
   6583  call setqflist([{'bufnr': b1}, {'bufnr': b2, 'lnum': 3}, {'bufnr': b3}], 'u')
   6584  call assert_equal(2, getqflist({'idx' : 0}).idx)
   6585 
   6586  " Update the quickfix list again. The currently selected entry (bufnr=b2, lnum=3)
   6587  " is no longer present. We should pick the nearest entry.
   6588  call setqflist([{'bufnr': b1}, {'bufnr': b2, 'lnum': 1}, {'bufnr': b2, 'lnum': 4}], 'u')
   6589  call assert_equal(3, getqflist({'idx' : 0}).idx)
   6590 
   6591  " Set the quickfix list again, with a specific column number. The currently selected entry doesn't have a
   6592  " column number, but they share a line number.
   6593  call setqflist([{'bufnr': b1}, {'bufnr': b2, 'lnum': 4, 'col': 5}, {'bufnr': b2, 'lnum': 4, 'col': 6}], 'u')
   6594  call assert_equal(2, getqflist({'idx' : 0}).idx)
   6595 
   6596  " Set the quickfix list again. The currently selected column number (6) is
   6597  " no longer present. We should select the nearest column number.
   6598  call setqflist([{'bufnr': b1}, {'bufnr': b2, 'lnum': 4, 'col': 2}, {'bufnr': b2, 'lnum': 4, 'col': 4}], 'u')
   6599  call assert_equal(3, getqflist({'idx' : 0}).idx)
   6600 
   6601  " Now set the quickfix list, but without columns. We should still pick the
   6602  " same line.
   6603  call setqflist([{'bufnr': b2, 'lnum': 3}, {'bufnr': b2, 'lnum': 4}, {'bufnr': b2, 'lnum': 4}], 'u')
   6604  call assert_equal(2, getqflist({'idx' : 0}).idx)
   6605 
   6606  " Cleanup the buffers we allocated during this test.
   6607  %bwipe!
   6608 endfunc
   6609 
   6610 " Test for "%b" in "errorformat"
   6611 func Test_efm_format_b()
   6612  call setqflist([], 'f')
   6613  new
   6614  call setline(1, ['1: abc', '1: def', '1: ghi'])
   6615  let b1 = bufnr()
   6616  new
   6617  call setline(1, ['2: abc', '2: def', '2: ghi'])
   6618  let b2 = bufnr()
   6619  new
   6620  call setline(1, ['3: abc', '3: def', '3: ghi'])
   6621  let b3 = bufnr()
   6622  new
   6623  let lines =<< trim eval END
   6624    {b1}:1:1
   6625    {b2}:2:2
   6626    {b3}:3:3
   6627  END
   6628  call setqflist([], ' ', #{lines: lines, efm: '%b:%l:%c'})
   6629  cfirst
   6630  call assert_equal([b1, 1, 1], [bufnr(), line('.'), col('.')])
   6631  cnext
   6632  call assert_equal([b2, 2, 2], [bufnr(), line('.'), col('.')])
   6633  cnext
   6634  call assert_equal([b3, 3, 3], [bufnr(), line('.'), col('.')])
   6635  enew!
   6636 
   6637  " Use a non-existing buffer
   6638  let lines =<< trim eval END
   6639    9991:1:1:m1
   6640    9992:2:2:m2
   6641    {b3}:3:3:m3
   6642  END
   6643  call setqflist([], ' ', #{lines: lines, efm: '%b:%l:%c:%m'})
   6644  cfirst | cnext
   6645  call assert_equal([b3, 3, 3], [bufnr(), line('.'), col('.')])
   6646  " Lines with non-existing buffer numbers should be used as non-error lines
   6647  call assert_equal([
   6648    \ #{lnum: 0, bufnr: 0, end_lnum: 0, pattern: '', valid: 0, vcol: 0, nr: -1,
   6649    \   module: '', type: '', end_col: 0, col: 0, text: '9991:1:1:m1'},
   6650    \ #{lnum: 0, bufnr: 0, end_lnum: 0, pattern: '', valid: 0, vcol: 0, nr: -1,
   6651    \   module: '', type: '', end_col: 0, col: 0, text: '9992:2:2:m2'},
   6652    \ #{lnum: 3, bufnr: b3, end_lnum: 0, pattern: '', valid: 1, vcol: 0,
   6653    \   nr: -1, module: '', type: '', end_col: 0, col: 3, text: 'm3'}],
   6654    \ getqflist())
   6655  %bw!
   6656  call setqflist([], 'f')
   6657 endfunc
   6658 
   6659 func XbufferTests_range(cchar)
   6660  call s:setup_commands(a:cchar)
   6661 
   6662  enew!
   6663  let lines =<< trim END
   6664    Xtestfile7:700:10:Line 700
   6665    Xtestfile8:800:15:Line 800
   6666  END
   6667  silent! call setline(1, lines)
   6668  norm! Vy
   6669  " Note: We cannot use :Xbuffer here,
   6670  " it doesn't properly fail, so we need to
   6671  " test using the raw c/l commands.
   6672  " (also further down)
   6673  if (a:cchar == 'c')
   6674     exe "'<,'>cbuffer!"
   6675  else
   6676    exe "'<,'>lbuffer!"
   6677  endif
   6678  let l = g:Xgetlist()
   6679  call assert_true(len(l) == 1 &&
   6680 \ l[0].lnum == 700 && l[0].col == 10 && l[0].text ==# 'Line 700')
   6681 
   6682  enew!
   6683  let lines =<< trim END
   6684    Xtestfile9:900:55:Line 900
   6685    Xtestfile10:950:66:Line 950
   6686  END
   6687  silent! call setline(1, lines)
   6688  if (a:cchar == 'c')
   6689    1cgetbuffer
   6690  else
   6691    1lgetbuffer
   6692  endif
   6693  let l = g:Xgetlist()
   6694  call assert_true(len(l) == 1 &&
   6695 \ l[0].lnum == 900 && l[0].col == 55 && l[0].text ==# 'Line 900')
   6696 
   6697  enew!
   6698  let lines =<< trim END
   6699    Xtestfile11:700:20:Line 700
   6700    Xtestfile12:750:25:Line 750
   6701  END
   6702  silent! call setline(1, lines)
   6703  if (a:cchar == 'c')
   6704    1,1caddbuffer
   6705  else
   6706    1,1laddbuffer
   6707  endif
   6708  let l = g:Xgetlist()
   6709  call assert_true(len(l) == 2 &&
   6710 \ l[0].lnum == 900 && l[0].col == 55 && l[0].text ==# 'Line 900' &&
   6711 \ l[1].lnum == 700 && l[1].col == 20 && l[1].text ==# 'Line 700')
   6712  enew!
   6713 
   6714  " Check for invalid range
   6715  " Using Xbuffer will not run the range check in the cbuffer/lbuffer
   6716  " commands. So directly call the commands.
   6717  if (a:cchar == 'c')
   6718      call assert_fails('900,999caddbuffer', 'E16:')
   6719  else
   6720      call assert_fails('900,999laddbuffer', 'E16:')
   6721  endif
   6722 endfunc
   6723 
   6724 func Test_cbuffer_range()
   6725  call XbufferTests_range('c')
   6726  call XbufferTests_range('l')
   6727 endfunc
   6728 
   6729 " Test for displaying fname passed from setqflist() when the names include
   6730 " hard links to prevent seemingly duplicate entries.
   6731 func Xtest_hardlink_fname(cchar)
   6732  call s:setup_commands(a:cchar)
   6733  %bwipe
   6734  " Create a sample source file
   6735  let lines =<< trim END
   6736    void sample() {}
   6737    int main() { sample(); return 0; }
   6738  END
   6739  call writefile(lines, 'test_qf_hardlink1.c', 'D')
   6740  defer delete('test_qf_hardlink1.c')
   6741  defer delete('test_qf_hardlink2.c')
   6742  call system('ln test_qf_hardlink1.c test_qf_hardlink2.c')
   6743  if v:shell_error
   6744    throw 'Skipped: ln throws error on this platform'
   6745  endif
   6746  call g:Xsetlist([], 'f')
   6747  " Make a qflist that contains the file and it's hard link
   6748  " like how LSP plugins set response into qflist
   6749  call g:Xsetlist([{'filename' : 'test_qf_hardlink1.c', 'lnum' : 1},
   6750        \ {'filename' : 'test_qf_hardlink2.c', 'lnum' : 1}], ' ')
   6751  Xopen
   6752  " Ensure that two entries are displayed with different name
   6753  " so that they aren't seen as duplication.
   6754  call assert_equal(['test_qf_hardlink1.c|1| ',
   6755        \ 'test_qf_hardlink2.c|1| '], getline(1, '$'))
   6756  Xclose
   6757 endfunc
   6758 
   6759 func Test_hardlink_fname()
   6760  CheckUnix
   6761  CheckExecutable ln
   6762  call Xtest_hardlink_fname('c')
   6763  call Xtest_hardlink_fname('l')
   6764 endfunc
   6765 
   6766 " Test for checking if correct number of tests are deleted
   6767 " and current list stays the same after setting Xhistory
   6768 " to a smaller number. Do roughly the same for growing the stack.
   6769 func Xtest_resize_list_stack(cchar)
   6770  call s:setup_commands(a:cchar)
   6771  Xsethist 100
   6772 
   6773  for i in range(1, 100)
   6774    Xexpr string(i)
   6775  endfor
   6776  Xopen
   6777  call assert_equal(g:Xgetlist({'nr': '$'}).nr, 100)
   6778  call assert_equal("|| 100", getline(1))
   6779  Xsethist 8
   6780  call assert_equal("|| 100", getline(1))
   6781  Xolder 5
   6782  call assert_equal("|| 95", getline(1))
   6783  Xsethist 6
   6784  call assert_equal("|| 95", getline(1))
   6785  Xsethist 1
   6786  call assert_equal("|| 100", getline(1))
   6787 
   6788  " grow array again
   6789  Xsethist 100
   6790  for i in range(1, 99)
   6791    Xexpr string(i)
   6792  endfor
   6793  call assert_equal("|| 99", getline(1))
   6794  Xolder 99
   6795  call assert_equal("|| 100", getline(1))
   6796 
   6797  Xsethistdefault
   6798 endfunc
   6799 
   6800 func Test_resize_list_stack()
   6801  call Xtest_resize_list_stack('c')
   6802  call Xtest_resize_list_stack('l')
   6803 endfunc
   6804 
   6805 " Test to check if order of lists is from
   6806 " oldest at the bottom to newest at the top
   6807 func Xtest_Xhistory_check_order(cchar)
   6808 
   6809  Xsethist 100
   6810 
   6811  for i in range(1, 100)
   6812    Xexpr string(i)
   6813  endfor
   6814 
   6815  Xopen
   6816  for i in range(100, 1, -1)
   6817    let l:ret = assert_equal("|| " .. i, getline(1))
   6818 
   6819    if ret == 1 || i == 1
   6820      break
   6821    endif
   6822    Xolder
   6823  endfor
   6824 
   6825  for i in range(1, 50)
   6826    Xexpr string(i)
   6827  endfor
   6828 
   6829  for i in range(50, 1, -1)
   6830    let l:ret = assert_equal("|| " .. i, getline(1))
   6831 
   6832    if ret == 1 || i == 50
   6833      break
   6834    endif
   6835    Xolder
   6836  endfor
   6837 
   6838  for i in range(50, 1, -1)
   6839    let l:ret = assert_equal("|| " .. i, getline(1))
   6840 
   6841    if ret == 1 || i == 50
   6842      break
   6843    endif
   6844    Xolder
   6845  endfor
   6846 
   6847  Xsethistdefault
   6848 endfunc
   6849 
   6850 func Test_set_history_to_check_order()
   6851  call Xtest_Xhistory_check_order('c')
   6852  call Xtest_Xhistory_check_order('l')
   6853 endfunc
   6854 
   6855 " Check if 'lhistory' is the same between the location list window
   6856 " and associated normal window
   6857 func Test_win_and_loc_synced()
   6858  new
   6859  set lhistory=2
   6860  lexpr "Text"
   6861  lopen
   6862 
   6863  " check if lhistory is synced when modified inside the
   6864  " location list window
   6865  setlocal lhistory=1
   6866  wincmd k
   6867  call assert_equal(&lhistory, 1)
   6868 
   6869  " check if lhistory is synced when modified inside the
   6870  " normal window
   6871  setlocal lhistory=10
   6872  lopen
   6873  call assert_equal(&lhistory, 10)
   6874 
   6875  wincmd k
   6876  lclose
   6877  wincmd q
   6878 
   6879  set lhistory&
   6880 endfunc
   6881 
   6882 " Test if setting the lhistory of one window doesn't affect the other
   6883 func Test_two_win_are_independent_of_history()
   6884  setlocal lhistory=10
   6885  new
   6886  setlocal lhistory=20
   6887  wincmd  w
   6888  call assert_equal(&lhistory, 10)
   6889  wincmd w
   6890  wincmd q
   6891 
   6892  set lhistory&
   6893 endfunc
   6894 
   6895 " Test if lhistory is copied over to a new window
   6896 func Test_lhistory_copied_over()
   6897  setlocal lhistory=3
   6898  split
   6899  call assert_equal(&lhistory, 3)
   6900  wincmd q
   6901 
   6902  set lhistory&
   6903 endfunc
   6904 
   6905 " Test if error occurs when given invalid history number
   6906 func Xtest_invalid_history_num(cchar)
   6907  call s:setup_commands(a:cchar)
   6908 
   6909  call assert_fails('Xsethist -10000', "E1542:")
   6910  call assert_fails('Xsethist 10000', "E1543:")
   6911  Xsethistdefault
   6912 endfunc
   6913 
   6914 func Test_invalid_history_num()
   6915  call Xtest_invalid_history_num('c')
   6916  call Xtest_invalid_history_num('l')
   6917 endfunc
   6918 
   6919 " Test if chistory and lhistory don't affect each other
   6920 func Test_chi_and_lhi_are_independent()
   6921  set chistory=100
   6922  set lhistory=100
   6923 
   6924  set chistory=10
   6925  call assert_equal(&lhistory, 100)
   6926 
   6927  set lhistory=1
   6928  call assert_equal(&chistory, 10)
   6929 
   6930  set chistory&
   6931  set lhistory&
   6932 endfunc
   6933 
   6934 func Test_quickfix_close_buffer_crash()
   6935  new
   6936  lexpr 'test' | lopen
   6937  wincmd k
   6938  lclose
   6939  wincmd q
   6940 endfunc
   6941 
   6942 func Test_vimgrep_dummy_buffer_crash()
   6943  augroup DummyCrash
   6944    autocmd!
   6945    " Make the dummy buffer non-current, but still open in a window.
   6946    autocmd BufReadCmd * ++once let s:dummy_buf = bufnr()
   6947          \| split | wincmd p | enew
   6948 
   6949    " Autocmds from cleaning up the dummy buffer in this case should be blocked.
   6950    autocmd BufWipeout *
   6951          \ call assert_notequal(s:dummy_buf, str2nr(expand('<abuf>')))
   6952  augroup END
   6953 
   6954  silent! vimgrep /./ .
   6955  redraw! " Window to freed dummy buffer used to remain; heap UAF.
   6956  call assert_equal([], win_findbuf(s:dummy_buf))
   6957  call assert_equal(0, bufexists(s:dummy_buf))
   6958 
   6959  unlet! s:dummy_buf
   6960  autocmd! DummyCrash
   6961  %bw!
   6962 endfunc
   6963 
   6964 func Test_vimgrep_dummy_buffer_keep()
   6965  augroup DummyKeep
   6966    autocmd!
   6967    " Trigger a wipe of the dummy buffer by aborting script processing. Prevent
   6968    " wiping it by splitting it from the autocmd window into an only window.
   6969    autocmd BufReadCmd * ++once let s:dummy_buf = bufnr()
   6970          \| tab split | call interrupt()
   6971  augroup END
   6972 
   6973  call assert_fails('vimgrep /./ .')
   6974  call assert_equal(1, bufexists(s:dummy_buf))
   6975  " Ensure it's no longer considered a dummy; should be able to switch to it.
   6976  execute s:dummy_buf 'sbuffer'
   6977 
   6978  unlet! s:dummy_buf
   6979  autocmd! DummyKeep
   6980  %bw!
   6981 endfunc
   6982 
   6983 func Test_quickfix_restore_current_win()
   6984  let curwin = win_getid()
   6985  vsplit Xb
   6986  wincmd p
   6987  botright copen
   6988  cclose
   6989 
   6990  call assert_equal(curwin, win_getid())
   6991  bw! Xb
   6992 endfunc
   6993 
   6994 func Test_quickfixtextfunc_wipes_buffer()
   6995  let g:crash=""
   6996  new
   6997  fu QFexpr(dummy)
   6998    bw
   6999  endfu
   7000  try
   7001    set quickfixtextfunc=QFexpr
   7002    lad "['0:4:e']"
   7003    lw
   7004  catch /^Vim\%((\S\+)\)\=:E565:/
   7005    let g:crash='caught'
   7006  endtry
   7007  " close location list window
   7008  bw
   7009  delfunc QFexpr
   7010  set quickfixtextfunc=
   7011  call assert_equal('caught', g:crash)
   7012  unlet g:crash
   7013  " close the newly opened window
   7014  bw
   7015 endfunc
   7016 
   7017 " vim: shiftwidth=2 sts=2 expandtab