neovim

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

test_search_stat.vim (20061B)


      1 " Tests for search_stats, when "S" is not in 'shortmess'
      2 
      3 source check.vim
      4 source screendump.vim
      5 
      6 func Test_search_stat()
      7  new
      8  set shortmess-=S
      9  " Append 50 lines with text to search for, "foobar" appears 20 times
     10  call append(0, repeat(['foobar', 'foo', 'fooooobar', 'foba', 'foobar'], 10))
     11 
     12  call cursor(1, 1)
     13 
     14  " searchcount() returns an empty dictionary when previous pattern was not set
     15  call assert_equal({}, searchcount(#{pattern: ''}))
     16  " but setting @/ should also work (even 'n' nor 'N' was executed)
     17  " recompute the count when the last position is different.
     18  call assert_equal(
     19    \ #{current: 1, exact_match: 1, total: 40, incomplete: 0, maxcount: 99},
     20    \ searchcount(#{pattern: 'foo'}))
     21  call assert_equal(
     22    \ #{current: 0, exact_match: 0, total: 10, incomplete: 0, maxcount: 99},
     23    \ searchcount(#{pattern: 'fooooobar'}))
     24  call assert_equal(
     25    \ #{current: 0, exact_match: 0, total: 10, incomplete: 0, maxcount: 99},
     26    \ searchcount(#{pattern: 'fooooobar', pos: [2, 1, 0]}))
     27  call assert_equal(
     28    \ #{current: 1, exact_match: 1, total: 10, incomplete: 0, maxcount: 99},
     29    \ searchcount(#{pattern: 'fooooobar', pos: [3, 1, 0]}))
     30  " on last char of match
     31  call assert_equal(
     32    \ #{current: 1, exact_match: 1, total: 10, incomplete: 0, maxcount: 99},
     33    \ searchcount(#{pattern: 'fooooobar', pos: [3, 9, 0]}))
     34  " on char after match
     35  call assert_equal(
     36    \ #{current: 1, exact_match: 0, total: 10, incomplete: 0, maxcount: 99},
     37    \ searchcount(#{pattern: 'fooooobar', pos: [3, 10, 0]}))
     38  call assert_equal(
     39    \ #{current: 1, exact_match: 0, total: 10, incomplete: 0, maxcount: 99},
     40    \ searchcount(#{pattern: 'fooooobar', pos: [4, 1, 0]}))
     41  call assert_equal(
     42    \ #{current: 1, exact_match: 0, total: 2, incomplete: 2, maxcount: 1},
     43    \ searchcount(#{pattern: 'fooooobar', pos: [4, 1, 0], maxcount: 1}))
     44  call assert_equal(
     45    \ #{current: 0, exact_match: 0, total: 2, incomplete: 2, maxcount: 1},
     46    \ searchcount(#{pattern: 'fooooobar', maxcount: 1}))
     47 
     48  " match at second line
     49  let messages_before = execute('messages')
     50  let @/ = 'fo*\(bar\?\)\?'
     51  let g:a = execute(':unsilent :norm! n')
     52  let stat = '\[2/50\]'
     53  let pat = escape(@/, '()*?'). '\s\+'
     54  call assert_match(pat .. stat, g:a)
     55  call assert_equal(
     56    \ #{current: 2, exact_match: 1, total: 50, incomplete: 0, maxcount: 99},
     57    \ searchcount(#{recompute: 0}))
     58  " didn't get added to message history
     59  call assert_equal(messages_before, execute('messages'))
     60 
     61  " Match at last line
     62  call cursor(line('$')-2, 1)
     63  let g:a = execute(':unsilent :norm! n')
     64  let stat = '\[50/50\]'
     65  call assert_match(pat .. stat, g:a)
     66  call assert_equal(
     67    \ #{current: 50, exact_match: 1, total: 50, incomplete: 0, maxcount: 99},
     68    \ searchcount(#{recompute: 0}))
     69 
     70  " No search stat
     71  set shortmess+=S
     72  call cursor(1, 1)
     73  let stat = '\[2/50\]'
     74  let g:a = execute(':unsilent :norm! n')
     75  call assert_notmatch(pat .. stat, g:a)
     76  " n does not update search stat
     77  call assert_equal(
     78    \ #{current: 50, exact_match: 1, total: 50, incomplete: 0, maxcount: 99},
     79    \ searchcount(#{recompute: 0}))
     80  call assert_equal(
     81    \ #{current: 2, exact_match: 1, total: 50, incomplete: 0, maxcount: 99},
     82    \ searchcount(#{recompute: v:true}))
     83  set shortmess-=S
     84 
     85  " Many matches
     86  call cursor(line('$')-2, 1)
     87  let @/ = '.'
     88  let pat = escape(@/, '()*?'). '\s\+'
     89  let g:a = execute(':unsilent :norm! n')
     90  let stat = '\[>99/>99\]'
     91  call assert_match(pat .. stat, g:a)
     92  call assert_equal(
     93    \ #{current: 100, exact_match: 0, total: 100, incomplete: 2, maxcount: 99},
     94    \ searchcount(#{recompute: 0}))
     95  call assert_equal(
     96    \ #{current: 272, exact_match: 1, total: 280, incomplete: 0, maxcount: 0},
     97    \ searchcount(#{recompute: v:true, maxcount: 0, timeout: 200}))
     98  call assert_equal(
     99    \ #{current: 1, exact_match: 1, total: 280, incomplete: 0, maxcount: 0},
    100    \ searchcount(#{recompute: 1, maxcount: 0, pos: [1, 1, 0], timeout: 200}))
    101  call cursor(line('$'), 1)
    102  let g:a = execute(':unsilent :norm! n')
    103  let stat = 'W \[1/>99\]'
    104  call assert_match(pat .. stat, g:a)
    105  call assert_equal(
    106    \ #{current: 1, exact_match: 1, total: 100, incomplete: 2, maxcount: 99},
    107    \ searchcount(#{recompute: 0}))
    108  call assert_equal(
    109    \ #{current: 1, exact_match: 1, total: 280, incomplete: 0, maxcount: 0},
    110    \ searchcount(#{recompute: 1, maxcount: 0, timeout: 200}))
    111  call assert_equal(
    112    \ #{current: 271, exact_match: 1, total: 280, incomplete: 0, maxcount: 0},
    113    \ searchcount(#{recompute: 1, maxcount: 0, pos: [line('$')-2, 1, 0], timeout: 200}))
    114 
    115  " Many matches
    116  call cursor(1, 1)
    117  let g:a = execute(':unsilent :norm! n')
    118  let stat = '\[2/>99\]'
    119  call assert_match(pat .. stat, g:a)
    120  call cursor(1, 1)
    121  let g:a = execute(':unsilent :norm! N')
    122  let stat = 'W \[>99/>99\]'
    123  call assert_match(pat .. stat, g:a)
    124 
    125  " right-left
    126  if exists("+rightleft")
    127    set rl
    128    call cursor(1,1)
    129    let @/ = 'foobar'
    130    let pat = 'raboof/\s\+'
    131    let g:a = execute(':unsilent :norm! n')
    132    let stat = '\[20/2\]'
    133    call assert_match(pat .. stat, g:a)
    134    set norl
    135  endif
    136 
    137  " right-left bottom
    138  if exists("+rightleft")
    139    set rl
    140    call cursor('$',1)
    141    let pat = 'raboof?\s\+'
    142    let g:a = execute(':unsilent :norm! N')
    143    let stat = '\[20/20\]'
    144    call assert_match(pat .. stat, g:a)
    145    set norl
    146  endif
    147 
    148  " right-left back at top
    149  if exists("+rightleft")
    150    set rl
    151    call cursor('$',1)
    152    let pat = 'raboof/\s\+'
    153    let g:a = execute(':unsilent :norm! n')
    154    let stat = 'W \[20/1\]'
    155    call assert_match(pat .. stat, g:a)
    156    set norl
    157  endif
    158 
    159  " normal, back at bottom
    160  call cursor(1,1)
    161  let @/ = 'foobar'
    162  let pat = '?foobar\s\+'
    163  let g:a = execute(':unsilent :norm! N')
    164  let stat = 'W \[20/20\]'
    165  call assert_match(pat .. stat, g:a)
    166  call assert_match('W \[20/20\]', Screenline(&lines))
    167 
    168  " normal, no match
    169  call cursor(1,1)
    170  let @/ = 'zzzzzz'
    171  let g:a = ''
    172  try
    173    let g:a = execute(':unsilent :norm! n')
    174  catch /^Vim\%((\a\+)\)\=:E486/
    175    let stat = ''
    176    " error message is not redir'ed to g:a, it is empty
    177    call assert_true(empty(g:a))
    178  catch
    179    call assert_false(1)
    180  endtry
    181 
    182  " with count
    183  call cursor(1, 1)
    184  let @/ = 'fo*\(bar\?\)\?'
    185  let g:a = execute(':unsilent :norm! 2n')
    186  let stat = '\[3/50\]'
    187  let pat = escape(@/, '()*?'). '\s\+'
    188  call assert_match(pat .. stat, g:a)
    189  let g:a = execute(':unsilent :norm! 2n')
    190  let stat = '\[5/50\]'
    191  call assert_match(pat .. stat, g:a)
    192 
    193  " with offset
    194  call cursor(1, 1)
    195  call feedkeys("/fo*\\(bar\\?\\)\\?/+1\<cr>", 'tx')
    196  let g:a = execute(':unsilent :norm! n')
    197  let stat = '\[5/50\]'
    198  let pat = escape(@/ .. '/+1', '()*?'). '\s\+'
    199  call assert_match(pat .. stat, g:a)
    200 
    201  " normal, n comes from a mapping
    202  "     Need to move over more than 64 lines to trigger char_avail(.
    203  nnoremap n nzv
    204  call cursor(1,1)
    205  call append(50, repeat(['foobar', 'foo', 'fooooobar', 'foba', 'foobar'], 10))
    206  call setline(2, 'find this')
    207  call setline(70, 'find this')
    208  let @/ = 'find this'
    209  let pat = '/find this\s\+'
    210  let g:a = execute(':unsilent :norm n')
    211  " g:a will contain several lines
    212  let g:b = split(g:a, "\n")[-1]
    213  let stat = '\[1/2\]'
    214  call assert_match(pat .. stat, g:b)
    215  unmap n
    216 
    217  " normal, but silent
    218  call cursor(1,1)
    219  let @/ = 'find this'
    220  let pat = '/find this\s\+'
    221  let g:a = execute(':norm! n')
    222  let stat = '\[1/2\]'
    223  call assert_notmatch(pat .. stat, g:a)
    224 
    225  " normal, n comes from a silent mapping
    226  " First test a normal mapping, then a silent mapping
    227  call cursor(1,1)
    228  nnoremap n n
    229  let @/ = 'find this'
    230  let pat = '/find this\s\+'
    231  let g:a = execute(':unsilent :norm n')
    232  let g:b = split(g:a, "\n")[-1]
    233  let stat = '\[1/2\]'
    234  call assert_match(pat .. stat, g:b)
    235  nnoremap <silent> n n
    236  call cursor(1,1)
    237  let g:a = execute(':unsilent :norm n')
    238  let g:b = split(g:a, "\n")[-1]
    239  let stat = '\[1/2\]'
    240  call assert_notmatch(pat .. stat, g:b)
    241  call assert_match(stat, g:b)
    242  " Test that the message is not truncated
    243  " it would insert '...' into the output.
    244  call assert_match('^\s\+' .. stat, g:b)
    245  unmap n
    246 
    247  " Time out
    248  %delete _
    249  call append(0, repeat(['foobar', 'foo', 'fooooobar', 'foba', 'foobar'], 100000))
    250  call cursor(1, 1)
    251  call assert_equal(1, searchcount(#{pattern: 'foo', maxcount: 0, timeout: 1}).incomplete)
    252 
    253  " Clean up
    254  set shortmess+=S
    255  " close the window
    256  bwipe!
    257 endfunc
    258 
    259 func Test_searchcount_fails()
    260  call assert_fails('echo searchcount("boo!")', 'E1206:')
    261  call assert_fails('echo searchcount({"timeout" : []})', 'E745:')
    262  call assert_fails('echo searchcount({"maxcount" : []})', 'E745:')
    263  call assert_fails('echo searchcount({"pattern" : []})', 'E730:')
    264  call assert_fails('echo searchcount({"pos" : 1})', 'E475:')
    265  call assert_fails('echo searchcount({"pos" : [1]})', 'E475:')
    266  call assert_fails('echo searchcount({"pos" : [[], 2, 3]})', 'E745:')
    267  call assert_fails('echo searchcount({"pos" : [1, [], 3]})', 'E745:')
    268  call assert_fails('echo searchcount({"pos" : [1, 2, []]})', 'E745:')
    269 endfunc
    270 
    271 func Test_search_stat_narrow_screen()
    272  " This used to crash Vim
    273  let save_columns = &columns
    274  try
    275    let after =<< trim [CODE]
    276      set laststatus=2
    277      set columns=16
    278      set shortmess-=S showcmd
    279      call setline(1, 'abc')
    280      call feedkeys("/abc\<CR>:quit!\<CR>")
    281      autocmd VimLeavePre * call writefile(["done"], "Xdone")
    282    [CODE]
    283 
    284    if !RunVim([], after, '--clean')
    285      return
    286    endif
    287    call assert_equal("done", readfile("Xdone")[0])
    288    call delete('Xdone')
    289  finally
    290    let &columns = save_columns
    291  endtry
    292 endfunc
    293 
    294 func Test_searchcount_in_statusline()
    295  CheckScreendump
    296 
    297  let lines =<< trim END
    298    set shortmess-=S
    299    call append(0, 'this is something')
    300    function TestSearchCount() abort
    301      let search_count = searchcount()
    302      if !empty(search_count)
    303 return '[' . search_count.current . '/' . search_count.total . ']'
    304      else
    305 return ''
    306      endif
    307    endfunction
    308    set hlsearch
    309    set laststatus=2 statusline+=%{TestSearchCount()}
    310  END
    311  call writefile(lines, 'Xsearchstatusline', 'D')
    312  let buf = RunVimInTerminal('-S Xsearchstatusline', #{rows: 10})
    313  call TermWait(buf)
    314  call term_sendkeys(buf, "/something")
    315  call VerifyScreenDump(buf, 'Test_searchstat_4', {})
    316 
    317  call term_sendkeys(buf, "\<Esc>")
    318  call StopVimInTerminal(buf)
    319 endfunc
    320 
    321 func Test_search_stat_foldopen()
    322  CheckScreendump
    323 
    324  let lines =<< trim END
    325    set shortmess-=S
    326    setl foldenable foldmethod=indent foldopen-=search
    327    call append(0, ['if', "\tfoo", "\tfoo", 'endif'])
    328    let @/ = 'foo'
    329    call cursor(1,1)
    330    norm n
    331  END
    332  call writefile(lines, 'Xsearchstat1', 'D')
    333 
    334  let buf = RunVimInTerminal('-S Xsearchstat1', #{rows: 10})
    335  call VerifyScreenDump(buf, 'Test_searchfoldopen_1', {})
    336 
    337  call term_sendkeys(buf, "n")
    338  call VerifyScreenDump(buf, 'Test_searchfoldopen_2', {})
    339 
    340  call term_sendkeys(buf, "n")
    341  call VerifyScreenDump(buf, 'Test_searchfoldopen_2', {})
    342 
    343  call StopVimInTerminal(buf)
    344 endfunc
    345 
    346 func! Test_search_stat_screendump()
    347  CheckScreendump
    348 
    349  let lines =<< trim END
    350    set shortmess-=S
    351    " Append 50 lines with text to search for, "foobar" appears 20 times
    352    call append(0, repeat(['foobar', 'foo', 'fooooobar', 'foba', 'foobar'], 20))
    353    call setline(2, 'find this')
    354    call setline(70, 'find this')
    355    nnoremap n n
    356    let @/ = 'find this'
    357    call cursor(1,1)
    358    norm n
    359  END
    360  call writefile(lines, 'Xsearchstat', 'D')
    361  let buf = RunVimInTerminal('-S Xsearchstat', #{rows: 10})
    362  call VerifyScreenDump(buf, 'Test_searchstat_1', {})
    363 
    364  call term_sendkeys(buf, ":nnoremap <silent> n n\<cr>")
    365  call term_sendkeys(buf, "gg0n")
    366  call VerifyScreenDump(buf, 'Test_searchstat_2', {})
    367 
    368  call StopVimInTerminal(buf)
    369 endfunc
    370 
    371 func Test_search_stat_then_gd()
    372  CheckScreendump
    373 
    374  let lines =<< trim END
    375    call setline(1, ['int cat;', 'int dog;', 'cat = dog;'])
    376    set shortmess-=S
    377    set hlsearch
    378  END
    379  call writefile(lines, 'Xsearchstatgd', 'D')
    380 
    381  let buf = RunVimInTerminal('-S Xsearchstatgd', #{rows: 10})
    382  call term_sendkeys(buf, "/dog\<CR>")
    383  call VerifyScreenDump(buf, 'Test_searchstatgd_1', {})
    384 
    385  call term_sendkeys(buf, "G0gD")
    386  call VerifyScreenDump(buf, 'Test_searchstatgd_2', {})
    387 
    388  call StopVimInTerminal(buf)
    389 endfunc
    390 
    391 func Test_search_stat_and_incsearch()
    392  CheckScreendump
    393 
    394  let lines =<< trim END
    395    call setline(1, ['abc--c', '--------abc', '--abc'])
    396    set hlsearch
    397    set incsearch
    398    set bg=dark
    399    set showtabline=2
    400 
    401    function MyTabLine()
    402    try
    403      let a=searchcount(#{recompute: 1, maxcount: -1})
    404      return a.current .. '/' .. a.total
    405    catch
    406      return ''
    407    endtry
    408    endfunction
    409 
    410    set tabline=%!MyTabLine()
    411  END
    412  call writefile(lines, 'Xsearchstat_inc', 'D')
    413 
    414  let buf = RunVimInTerminal('-S Xsearchstat_inc', #{rows: 10})
    415  call term_sendkeys(buf, "/abc")
    416  call TermWait(buf)
    417  call VerifyScreenDump(buf, 'Test_searchstat_inc_1', {})
    418 
    419  call term_sendkeys(buf, "\<c-g>")
    420  call TermWait(buf)
    421  call VerifyScreenDump(buf, 'Test_searchstat_inc_2', {})
    422 
    423  call term_sendkeys(buf, "\<c-g>")
    424  call TermWait(buf)
    425  call VerifyScreenDump(buf, 'Test_searchstat_inc_3', {})
    426 
    427  call term_sendkeys(buf, "\<esc>:qa\<cr>")
    428  call TermWait(buf)
    429 
    430  call StopVimInTerminal(buf)
    431 endfunc
    432 
    433 func Test_search_stat_backwards()
    434  CheckScreendump
    435 
    436  let lines =<< trim END
    437    set shm-=S
    438    call setline(1, ['test', ''])
    439  END
    440  call writefile(lines, 'Xsearchstat_back', 'D')
    441 
    442  let buf = RunVimInTerminal('-S Xsearchstat_back', #{rows: 10})
    443  call term_sendkeys(buf, "*")
    444  call TermWait(buf)
    445  call VerifyScreenDump(buf, 'Test_searchstat_back_1', {})
    446 
    447  call term_sendkeys(buf, "N")
    448  call TermWait(buf)
    449  call VerifyScreenDump(buf, 'Test_searchstat_back_2', {})
    450 
    451  call term_sendkeys(buf, ":set shm+=S\<cr>N")
    452  call TermWait(buf)
    453  " shows "Search Hit Bottom.."
    454  call VerifyScreenDump(buf, 'Test_searchstat_back_3', {})
    455 
    456  call term_sendkeys(buf, "\<esc>:qa\<cr>")
    457  call TermWait(buf)
    458 
    459  call StopVimInTerminal(buf)
    460 endfunc
    461 
    462 func Test_search_stat_smartcase_ignorecase()
    463  CheckRunVimInTerminal
    464 
    465  let lines =<< trim END
    466    set shm-=S ignorecase smartcase
    467    call setline(1, [' MainmainmainmmmainmAin', ''])
    468  END
    469  call writefile(lines, 'Xsearchstat_ignorecase', '5')
    470 
    471  let buf = RunVimInTerminal('-S Xsearchstat_ignorecase', #{rows: 10})
    472  call term_sendkeys(buf, "/main\<cr>nnnn")
    473  call WaitForAssert({-> assert_match('\[5\/5\]', term_getline(buf, 10))}, 1000)
    474 
    475  call term_sendkeys(buf, "/mAin\<cr>")
    476  call WaitForAssert({-> assert_match('\[1\/1\]', term_getline(buf, 10))}, 1000)
    477 
    478  call StopVimInTerminal(buf)
    479 endfunc
    480 
    481 func Test_search_stat_option_values()
    482  call assert_fails(':set maxsearchcount=0', 'E487:')
    483  call assert_fails(':set maxsearchcount=10000', 'E474:')
    484  set maxsearchcount=9999
    485  call assert_equal(9999, &msc)
    486  set maxsearchcount=1
    487  call assert_equal(1, &msc)
    488  set maxsearchcount=999
    489  call assert_equal(999, &msc)
    490  set maxsearchcount&vim
    491 endfunc
    492 
    493 func Test_search_stat_option()
    494  " Asan causes wrong results, because the search times out
    495  CheckNotAsan
    496  " Mark the test as flaky as the search may still occasionally time out
    497  let g:test_is_flaky = 1
    498 
    499  enew
    500  set shortmess-=S
    501  set maxsearchcount=999
    502  " Append 1000 lines with text to search for, "foobar" appears 20 times
    503  call append(0, repeat(['foobar', 'foo', 'fooooobar', 'foba', 'foobar'], 1000))
    504 
    505  call cursor(1, 1)
    506  call assert_equal(
    507    \ #{exact_match: 1, current: 1, incomplete: 2, maxcount: 999, total: 1000},
    508    \ searchcount(#{pattern: 'fooooobar', pos: [3, 1, 0]}))
    509  " on last char of match
    510  call assert_equal(
    511    \ #{exact_match: 1, current: 1, incomplete: 2, maxcount: 999, total: 1000},
    512    \ searchcount(#{pattern: 'fooooobar', pos: [3, 9, 0]}))
    513  " on char after match
    514  call assert_equal(
    515    \ #{exact_match: 0, current: 1, incomplete: 2, maxcount: 999, total: 1000},
    516    \ searchcount(#{pattern: 'fooooobar', pos: [3, 10, 0]}))
    517 
    518  " match at second line
    519  let messages_before = execute('messages')
    520  let @/ = 'fo*\(bar\?\)\?'
    521  let g:a = execute(':unsilent :norm! n')
    522  let stat = '\[2/>999\]'
    523  let pat = escape(@/, '()*?'). '\s\+'
    524  call assert_match(pat .. stat, g:a)
    525  call assert_equal(
    526    \ #{exact_match: 1, current: 2, incomplete: 2, maxcount: 999, total: 1000},
    527    \ searchcount(#{recompute: 0}))
    528  " didn't get added to message history
    529  call assert_equal(messages_before, execute('messages'))
    530 
    531  " If the test is being retried due to flakiness, extend the searchcount()
    532  " timeout, too
    533  let timeout = 500 * get(g:, 'run_nr', 1)
    534 
    535  " Many matches
    536  call cursor(line('$')-2, 1)
    537  let @/ = '.'
    538  let pat = escape(@/, '()*?'). '\s\+'
    539  let g:a = execute(':unsilent :norm! n')
    540  let stat = '\[>999/>999\]'
    541  call assert_match(pat .. stat, g:a)
    542  call assert_equal(
    543    \ #{exact_match: 0, current: 1000, incomplete: 2, maxcount: 999, total: 1000},
    544    \ searchcount(#{recompute: 0}))
    545  call assert_equal(
    546    \ #{exact_match: 1, current: 27992, incomplete: 0, maxcount:0, total: 28000},
    547    \ searchcount(#{recompute: v:true, maxcount: 0, timeout: timeout}))
    548  call assert_equal(
    549    \ #{exact_match: 1, current: 1, incomplete: 0, maxcount: 0, total: 28000},
    550    \ searchcount(#{recompute: 1, maxcount: 0, pos: [1, 1, 0], timeout: timeout}))
    551  call cursor(line('$'), 1)
    552  let g:a = execute(':unsilent :norm! n')
    553  let stat = 'W \[1/>999\]'
    554  call assert_match(pat .. stat, g:a)
    555  call assert_equal(
    556    \ #{current: 1, exact_match: 1, total: 1000, incomplete: 2, maxcount: 999},
    557    \ searchcount(#{recompute: 0}))
    558  call assert_equal(
    559    \ #{current: 1, exact_match: 1, total: 28000, incomplete: 0, maxcount: 0},
    560    \ searchcount(#{recompute: 1, maxcount: 0, timeout: timeout}))
    561  call assert_equal(
    562    \ #{current: 27991, exact_match: 1, total: 28000, incomplete: 0, maxcount: 0},
    563    \ searchcount(#{recompute: 1, maxcount: 0, pos: [line('$')-2, 1, 0], timeout: timeout}))
    564 
    565  " Many matches
    566  call cursor(1, 1)
    567  let g:a = execute(':unsilent :norm! n')
    568  let stat = '\[2/>999\]'
    569  call assert_match(pat .. stat, g:a)
    570  call cursor(1, 1)
    571  let g:a = execute(':unsilent :norm! N')
    572  let stat = '\[>999/>999\]'
    573  call assert_match(pat .. stat, g:a)
    574  set maxsearchcount=500
    575  call cursor(1, 1)
    576  let g:a = execute(':unsilent :norm! n')
    577  let stat = '\[2/>500\]'
    578  call assert_match(pat .. stat, g:a)
    579  call cursor(1, 1)
    580  let g:a = execute(':unsilent :norm! N')
    581  let stat = '\[>500/>500\]'
    582  call assert_match(pat .. stat, g:a)
    583  set maxsearchcount=20
    584  call cursor(1, 1)
    585  let g:a = execute(':unsilent :norm! n')
    586  let stat = '\[2/>20\]'
    587  call assert_match(pat .. stat, g:a)
    588  call cursor(1, 1)
    589  let g:a = execute(':unsilent :norm! N')
    590  let stat = '\[>20/>20\]'
    591  call assert_match(pat .. stat, g:a)
    592  set maxsearchcount=999
    593 
    594  " right-left
    595  if exists("+rightleft")
    596    set rl
    597    call cursor(1,1)
    598    let @/ = 'foobar'
    599    let pat = 'raboof/\s\+'
    600    let g:a = execute(':unsilent :norm! n')
    601    let stat = '\[>999/2\]'
    602    call assert_match(pat .. stat, g:a)
    603 
    604    " right-left bottom
    605    call cursor('$',1)
    606    let pat = 'raboof?\s\+'
    607    let g:a = execute(':unsilent :norm! N')
    608    let stat = '\[>999/>999\]'
    609    call assert_match(pat .. stat, g:a)
    610 
    611    " right-left back at top
    612    call cursor('$',1)
    613    let pat = 'raboof/\s\+'
    614    let g:a = execute(':unsilent :norm! n')
    615    let stat = 'W \[>999/1\]'
    616    call assert_match(pat .. stat, g:a)
    617    set norl
    618  endif
    619 
    620  " normal, back at bottom
    621  call cursor(1,1)
    622  let @/ = 'foobar'
    623  let pat = '?foobar\s\+'
    624  let g:a = execute(':unsilent :norm! N')
    625  let stat = 'W \[>999/>999\]'
    626  call assert_match(pat .. stat, g:a)
    627  call assert_match('W \[>999/>999\]', Screenline(&lines))
    628 
    629  " normal, no match
    630  call cursor(1,1)
    631  let @/ = 'zzzzzz'
    632  let g:a = ''
    633  try
    634    let g:a = execute(':unsilent :norm! n')
    635  catch /^Vim\%((\a\+)\)\=:E486/
    636    let stat = ''
    637    " error message is not redir'ed to g:a, it is empty
    638    call assert_true(empty(g:a))
    639  catch
    640    call assert_false(1)
    641  endtry
    642 
    643  " Clean up
    644  set shortmess+=S
    645  set maxsearchcount&vim
    646  " close the window
    647  bwipe!
    648 endfunc
    649 
    650 " vim: shiftwidth=2 sts=2 expandtab