Location list cannot be used/tested after caught error
ratfactor opened this issue · 6 comments
When any Vim error occurs during a Vader test (despite being caught by a try/catch
block), any further attempts to read from the location list will fail.
Example (test.vader
):
Execute (Test location list):
lvimgrep /i_will_match/ test.vader
Log getloclist(0)
Assert !empty(getloclist(0))
Execute (Test location list after "error"):
try | lvimgrep /^no-match/ test.vader | catch | endtry
lvimgrep /i_should_match/ test.vader
Log getloclist(0)
Assert !empty(getloclist(0))
The first test will succeed (the location list returned by getloclist(0)
contains the results of the lvimgrep
command.
The second test intentionally fails to match and lvimgrep
throws an error, which we catch.
That's fine.
But thereafter, any subsequent attempts to perform an lvimgrep
and inspect the location list will fail (getloclist(0)
returns an empty list).
The Vader results:
Starting Vader: 1 suite(s), 2 case(s)
Starting Vader: /home/dave/.vim/bundle/vimwiki/test/test.vader
(1/2) [EXECUTE] Test location list
> [{'lnum': 2, 'bufnr': 1, 'col': 13, 'valid': 1, 'vcol': 0, 'nr': 0, 'type': '', 'pattern': '', 'text': ' lvimgrep /i_will_match/ test.vader'}]
(2/2) [EXECUTE] Test location list after "error"
> []
(2/2) [EXECUTE] (X) Assertion failure
Success/Total: 1/2
Success/Total: 1/2 (assertions: 1/2)
Elapsed time: 0.034826 sec.
What does work:
- Running
lvimgrep
manually and inspecting the location list with:echo getloclist(0)
- Doing the above manually after a failed search or any other error
- Running any number of
lvimgrep
searches in Vader tests...until an error is thrown
Any fix, work-around, or alternative way of testing lvimgrep
results with Vader would be appreciated.
Likely related to Vader using a location list itself for errors?
Try new
before, with bwipe
after.
As near as I can tell, Vader itself does not write to the location list. (It does use the quickfix list.)
However, following your suggestion, and after playing around with a ridiculous number of variations for the last couple days and using the process of elimination, I can now make a test case pass...but I don't understand why it passes and the whole thing feels incredibly fragile.
Check out this crazy setup
test2.vim:
silent lvimgrep foo /tmp/contains_foo
test2.vader:
Execute:
function! Srch(for, should_match)
new
try
execute 'silent lvimgrep'.a:for.' /tmp/contains_foo'
catch | endtry
if a:should_match
Assert len(getloclist(0)) > 0, "Should match"
else
Assert len(getloclist(0)) == 0, "No matches"
endif
bwipe
endfunction
call Srch('/foo/', 1)
call Srch('/no-match/', 0)
call Srch('/foo/', 1)
I invoke this with:
vim '+so test2.vim' '+Vader! test2.vader'
And it passes:
Success/Total: 1/1 (assertions: 3/3)
Take away any of the secret ingredients and it fails:
- Don't run
test2.vim
first...FAIL! - Remove the
new
...FAIL! - Remove the
bwipe
...FAIL!
This doesn't happen in plain Vimscript
test3.vim:
function! Srch(for, should_match)
try
execute 'silent lvimgrep'.a:for.' /tmp/contains_foo'
catch | endtry
if a:should_match && len(getloclist(0)) > 0
echom "match"
else
echom "NO match"
endif
endfunction
call Srch('/foo/', 1)
call Srch('/no-match/', 0)
call Srch('/foo/', 1)
Reliably outputs:
:source test3.vim
:messages
match
NO match
match
You can add the new
and bwipe
around the search. Works just fine. Do anything you like, it always works just fine.
I've not been able to replicate the lvimgrep/getloclist()
failure outside of Vader.
Another weird thing
I thought this was worth noting as well: lvimgrep
doesn't even seem to throw an error after the first failed match is caught in a Vader script:
Execute:
Log "Fail a match, catch the error."
try
lvimgrep /no-match/ /tmp/contains_foo
catch | endtry
Log "Fail a match again, don't even bother catching the error."
lvimgrep /no-match2/ /tmp/contains_foo
Assert 1
The above test will succeed every time in my copy of Vim 7.4.
Starting Vader: 1 suite(s), 1 case(s)
Starting Vader: /home/dave/test3.vader
(1/1) [EXECUTE]
> Fail a match, catch the error.
> Fail a match again, don't even bother catching the error.
Success/Total: 1/1
Success/Total: 1/1 (assertions: 1/1)
Change the first lvimgrep
search to a successful match (/foo/
) or remove it and the second failed match will throw an error and the test will fail.
(1/1) [EXECUTE] (X) Vim(lvimgrep):E480: No match: no-match2
I would love to understand what is happening here.
Maybe it helps to try my branch from #107 - might provide better error messages.
Otherwise you could also try using Neovim and/or the most recent Vim, of course.
@blueyed I really like the improvements in your display-source-with-exceptions
branch! Sadly, it did not reveal anything new for this particular problem.
I also ran my tests on Neovim with identical results, so I feel pretty confident this is a Vader-specific problem.
I might start combing through the Vader source to see if I can pinpoint exactly where everything goes wrong - somewhere between executing commands and opening tabs/windows? Any pointers on where to start looking would be appreciated.
I've given up on this for now. I dived into it several times, but never learned anything satisfying.
Thanks for your help @blueyed.
I've opted to simply sidestep the problem by making my Vader tests independent.
From this:
vim "+Vader! test/*"
To this:
for VADER_FILE in test/*.vader
do
vim "+Vader! $VADER_FILE"
done
Which guarantees that no errors will be thrown in a Vim/Vader session before I get a chance to make assertions on the output of lvimgrep
.