Skip to content

Commit

Permalink
test.vim: more efficient compiling of test files
Browse files Browse the repository at this point in the history
This change improves the way we compile a Go test. Previously we would
build a test binary to catch any build errors. A callback was then
responsible to delete the test binary after showing build errors (if
there were any).

This could be racy though, because if the tests lasts long and we quit
early, the callback to clean the binary file would never run. So we
would end up with artifacts in our working directory.

To fix the issue we're going to tell to the `go` tool to run a specific,
unique function. We're passing a unique identifier as a function name
(which is a randomly generated). This will cause the go tool to build
the test file and then try to run the test function. Because there is no
such test function, it'll silently quit with zero exit status. As a side
effect it'll compile the test file, so we're able to catch any build
errors (if any)

fixes #907
  • Loading branch information
fatih committed Jun 2, 2017
1 parent 7fafcb1 commit df8ced7
Showing 1 changed file with 6 additions and 37 deletions.
43 changes: 6 additions & 37 deletions autoload/go/test.vim
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ function! go#test#Test(bang, compile, ...) abort

" don't run the test, only compile it. Useful to capture and fix errors.
if a:compile
let compile_file = "vim-go-test-compile"
call extend(args, ["-c", "-o", compile_file])
" we're going to tell to run a test function that doesn't exist. This
" triggers a build of the test file itself but no tests will run.
call extend(args, ["-run", "499EE4A2-5C85-4D35-98FC-7377CD87F263"])
endif

if a:0
Expand Down Expand Up @@ -45,13 +46,10 @@ function! go#test#Test(bang, compile, ...) abort
\ 'bang': a:bang,
\ 'winnr': winnr(),
\ 'dir': getcwd(),
\ 'compile_test': a:compile,
\ 'jobdir': fnameescape(expand("%:p:h")),
\ }

if a:compile
let job_args['compile_cb'] = function('s:test_compile', [compile_file])
endif

call s:test_job(job_args)
return
elseif has('nvim')
Expand All @@ -62,10 +60,6 @@ function! go#test#Test(bang, compile, ...) abort
let id = go#jobcontrol#Spawn(a:bang, "test", args)
endif

if a:compile
call go#jobcontrol#AddHandler(function('s:test_compile_handler'))
let s:test_compile_handlers[id] = compile_file
endif
return id
endif

Expand All @@ -81,10 +75,6 @@ function! go#test#Test(bang, compile, ...) abort
let dir = getcwd()
execute cd fnameescape(expand("%:p:h"))

if a:compile
call delete(compile_file)
endif

if go#util#ShellError() != 0
let errors = s:parse_errors(split(out, '\n'))
let errors = go#tool#FilterValids(errors)
Expand Down Expand Up @@ -150,7 +140,7 @@ function s:test_job(args) abort
\ 'state': "started",
\ }

if has_key(a:args, 'compile_cb')
if a:args.compile_test
let status.state = "compiling"
endif

Expand All @@ -171,8 +161,7 @@ function s:test_job(args) abort
\ 'state': "pass",
\ }

if has_key(a:args, 'compile_cb')
call a:args.compile_cb(a:job, a:exitval, messages)
if a:args.compile_test
let status.state = "success"
endif

Expand Down Expand Up @@ -282,25 +271,5 @@ function! s:parse_errors(lines) abort
return errors
endfunction

" test_compile is called when a GoTestCompile call is finished
function! s:test_compile(test_file, job, exit_status, data) abort
call delete(a:test_file)
endfunction

" -----------------------
" | Neovim job handlers |
" -----------------------
let s:test_compile_handlers = {}

function! s:test_compile_handler(job, exit_status, data) abort
if !has_key(s:test_compile_handlers, a:job.id)
return
endif
let l:compile_file = s:test_compile_handlers[a:job.id]
call delete(l:compile_file)
unlet s:test_compile_handlers[a:job.id]
endfunction


" vim: sw=2 ts=2 et
"

0 comments on commit df8ced7

Please sign in to comment.