AndrewRadev/vimrunner

Tracking coverage with vimrunner

blueyed opened this issue · 5 comments

I am trying to track coverage with vimrunner (via https://github.com/Vimjas/covimerage/), but the problem appears to be that it spawns a gvim instance without waiting for it.

My current attempt is to have a gvim wrapper, which I inject into the $PATH (it would be good to explicitly provide the executable btw):

#!/bin/sh

# echo "$@" >> /tmp/1l
# echo "$1" >> /tmp/1l

if [ "$1" = "--noplugin" ]; then
    echo "Running covimerage run /usr/bin/gvim $*" > /tmp/1l
    exec 1>>/tmp/1l
    exec 2>>/tmp/1l
    echo "running" >> /tmp/1l
    covimerage -vv run --profile-file /tmp/foo.profile --source "$PWD" /usr/bin/gvim -f "$@"
else
    exec /usr/bin/gvim "$@"
fi

I've tried using & and wait here, but this script is already affected by the PTY.spawn.

Any hints?

I'll have to look into covimerage and how it works, and experiment a bit maybe. For now, I could at least give you some things to try.

For starters:

(it would be good to explicitly provide the executable btw)

It's actually possible. Here's the implementation of the Vimrunner.start_gvim method:

def self.start_gvim(&blk)
Server.new(:executable => Platform.gvim).start(&blk)
end

Basically, there's a Server, which connects to the Vim instance, and holds pids and such, and a Client, which provides wrappers around common commands. The server's start method returns a Client. You could, theoretically, run your script without PATH manipulations by:

vim = Server.new(executable: "/path/to/my-gvim").start

You could also create an existing Vim instance, and then connect to it, as long as you spawn a Vim with a particular servername. Take a look at the documentation for connect: http://www.rubydoc.info/gems/vimrunner/0.3.4/Vimrunner. Maybe you could spawn your instance, prepare it however you like, and then run Vimrunner with it?

Thanks!

As for executable, I am using this:

vim = Vimrunner::Server.new(:executable => Dir.getwd + "/bin/gvim").start()

This is for a Vim plugin, which has some spec helpers already (https://github.com/Vimjas/vim-python-pep8-indent/blob/master/spec/spec_helper.rb), and I can use an env var for this then.

Some findings:
even when using the "TERM" signal instead of "KILL" to kill the vimrunner server (using Process.kill("TERM", @pid)), it will result in:

Vim: Caught deadly signal HUP
Vim: Finished.

This is the case for both using xvfb-run or without (i.e. gvim being visible).
This results in covimerage (which runs rspec) to being killed directly.

I have moved/commented the @r.close and @w.close for this, otherwise the SIGHUP is send before it seems (which makes sense since the pty hung up).

When using Process.wait(@pid) and manually killing the visible gvim, I get the SIGTERM, and covimerage can handle that, i.e. proceed.

covimerage uses Python's subprocess.call.

One easy fix for this is to use remote_expr("VimrunnerEvaluateCommandOutput('quitall!')") (or a simpler version of it) in kill, then wait for the process (possibly with some timeout), falling back to TERM (instead of KILL).

Using Server.connect is a good method.
I've created #52 nonethess to improve the kill behavior.

Hmm, the problem seems to be rather that the SIGHUP is not forwarded to Vim by covimerage.

Using connect requires to overwrite kill though, since it might fail with @r being nil otherwise:

  config.start_vim do
    vim = Vimrunner.connect(ENV['PYTHON_PEP8_INDENT_TEST_VIM_SERVERNAME'])
    def vim.kill
      normal(":quitall!<CR>")
    end