Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Location list cannot be used/tested after caught error #199

Open
ratfactor opened this issue Sep 26, 2019 · 6 comments
Open

Location list cannot be used/tested after caught error #199

ratfactor opened this issue Sep 26, 2019 · 6 comments

Comments

@ratfactor
Copy link

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.

@blueyed
Copy link
Collaborator

blueyed commented Sep 26, 2019

Likely related to Vader using a location list itself for errors?

Try new before, with bwipe after.

@ratfactor
Copy link
Author

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.

@blueyed
Copy link
Collaborator

blueyed commented Sep 30, 2019

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.

@ratfactor
Copy link
Author

@blueyed - Thanks, I'll try your branch and other versions of (Neo)vim.

@ratfactor
Copy link
Author

@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.

@ratfactor
Copy link
Author

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants