Run all tests in NeoVim, improve the test script, and make all tests pass for NeoVim

This commit is contained in:
w0rp 2017-05-12 20:38:52 +01:00
parent 07b2542c0d
commit 2bafdb7e5a
10 changed files with 287 additions and 94 deletions

View File

@ -7,4 +7,4 @@ branches:
- master - master
language: python language: python
script: | script: |
make test ./run-tests

View File

@ -1,53 +0,0 @@
SHELL := /usr/bin/env bash
IMAGE ?= w0rp/ale
CURRENT_IMAGE_ID = 30a9967dbdb1
DOCKER_FLAGS = --rm -v $(PWD):/testplugin -v $(PWD)/test:/home "$(IMAGE)"
tests = test/*.vader test/*/*.vader test/*/*/*.vader test/*/*/*/*.vader
test-setup:
docker images -q w0rp/ale | grep ^$(CURRENT_IMAGE_ID) > /dev/null || \
docker pull $(IMAGE)
vader: test-setup
@:; \
vims=$$(docker run --rm $(IMAGE) ls /vim-build/bin | grep -E '^n?vim'); \
if [ -z "$$vims" ]; then echo "No Vims found!"; exit 1; fi; \
for vim in $$vims; do \
docker run -a stderr $(DOCKER_FLAGS) $$vim '+Vader! $(tests)'; \
done
test: test-setup
@:; \
vims=$$(docker run --rm $(IMAGE) ls /vim-build/bin | grep -E '^n?vim'); \
if [ -z "$$vims" ]; then echo "No Vims found!"; exit 1; fi; \
EXIT=0; \
for vim in $$vims; do \
echo; \
echo '========================================'; \
echo "Running tests for $$vim"; \
echo '========================================'; \
echo; \
docker run -a stderr $(DOCKER_FLAGS) $$vim '+Vader! $(tests)' || EXIT=$$?; \
done; \
echo; \
echo '========================================'; \
echo 'Running Vint to lint our code'; \
echo '========================================'; \
echo 'Vint warnings/errors follow:'; \
echo; \
set -o pipefail; \
docker run -a stdout $(DOCKER_FLAGS) vint -s /testplugin | sed s:^/testplugin/:: || EXIT=$$?; \
set +o pipefail; \
echo; \
echo '========================================'; \
echo 'Running custom checks'; \
echo '========================================'; \
echo 'Custom warnings/errors follow:'; \
echo; \
set -o pipefail; \
docker run -v $(PWD):/testplugin "$(IMAGE)" /testplugin/custom-checks /testplugin | sed s:^/testplugin/:: || EXIT=$$?; \
set +o pipefail; \
echo; \
exit $$EXIT;
.DEFAULT_GOAL := test

View File

@ -283,6 +283,10 @@ function! s:HandleExit(job) abort
return return
endif endif
if has('nvim') && !empty(l:output) && empty(l:output[-1])
call remove(l:output, -1)
endif
if l:next_chain_index < len(get(l:linter, 'command_chain', [])) if l:next_chain_index < len(get(l:linter, 'command_chain', []))
call s:InvokeChain(l:buffer, l:linter, l:next_chain_index, l:output) call s:InvokeChain(l:buffer, l:linter, l:next_chain_index, l:output)
return return
@ -773,6 +777,17 @@ function! ale#engine#WaitForJobs(deadline) abort
call extend(l:job_list, l:info.job_list) call extend(l:job_list, l:info.job_list)
endfor endfor
" NeoVim has a built-in API for this, so use that.
if has('nvim')
let l:nvim_code_list = jobwait(l:job_list, a:deadline)
if index(l:nvim_code_list, -1) >= 0
throw 'Jobs did not complete on time!'
endif
return
endif
let l:should_wait_more = 1 let l:should_wait_more = 1
while l:should_wait_more while l:should_wait_more

171
run-tests Executable file
View File

@ -0,0 +1,171 @@
#!/bin/bash -eu
# Author: w0rp <devw0rp@gmail.com>
#
# This script runs tests for the ALE project. The following options are
# accepted:
#
# -v Enable verbose output
# --neovim-only Run tests only for NeoVim
# --vim-only Run tests only for Vim
RED='\033[0;31m'
GREEN='\033[0;32m'
NC='\033[0m'
CURRENT_IMAGE_ID=d5a1b5915b09
IMAGE=w0rp/ale
DOCKER_FLAGS=(--rm -v "$PWD:/testplugin" -v "$PWD/test:/home" -w /testplugin "$IMAGE")
EXIT=0
tests='test/*.vader test/*/*.vader test/*/*/*.vader test/*/*/*.vader'
verbose=0
run_neovim_tests=1
run_vim_tests=1
run_vint=1
run_custom_checks=1
while [ $# -ne 0 ]; do
case $1 in
-v)
verbose=1
shift
;;
--neovim-only)
run_vim_tests=0
run_vint=0
run_custom_checks=0
shift
;;
--vim-only)
run_neovim_tests=0
run_vint=0
run_custom_checks=0
;;
--)
shift
break
;;
-?*)
echo "Invalid argument: $1" 1>&2
exit 1
;;
*)
break
;;
esac
done
# Allow tests to be passed as arguments.
if [ $# -ne 0 ]; then
# This doesn't perfectly handle work splitting, but none of our files
# have spaces in the names.
tests="$*"
fi
docker images -q w0rp/ale | grep "^$CURRENT_IMAGE_ID" > /dev/null \
|| docker pull "$IMAGE"
function color-vader-output() {
local vader_started=0
while read -r; do
if ((!verbose)); then
# When verbose mode is off, suppress output until Vader starts.
if ((!vader_started)); then
if [[ "$REPLY" = *'Starting Vader:'* ]]; then
vader_started=1
else
continue
fi
fi
fi
if [[ "$REPLY" = *'[EXECUTE] (X)'* ]]; then
echo -en "$RED"
elif [[ "$REPLY" = *'[EXECUTE]'* ]] || [[ "$REPLY" = *'[ GIVEN]'* ]]; then
echo -en "$NC"
fi
if [[ "$REPLY" = *'Success/Total'* ]]; then
success="$(echo -n "$REPLY" | grep -o '[0-9]\+/' | head -n1 | cut -d/ -f1)"
total="$(echo -n "$REPLY" | grep -o '/[0-9]\+' | head -n1 | cut -d/ -f2)"
if [ "$success" -lt "$total" ]; then
echo -en "$RED"
else
echo -en "$GREEN"
fi
echo "$REPLY"
echo -en "$NC"
else
echo "$REPLY"
fi
done
echo -en "$NC"
}
if ((run_neovim_tests)); then
for vim in $(docker run --rm "$IMAGE" ls /vim-build/bin | grep '^neovim' ); do
echo
echo '========================================'
echo "Running tests for $vim"
echo '========================================'
echo
set -o pipefail
docker run -it -e VADER_OUTPUT_FILE=/dev/stderr "${DOCKER_FLAGS[@]}" \
"/vim-build/bin/$vim" -u test/vimrc \
--headless "+Vader! $tests" | color-vader-output || EXIT=$?
set +o pipefail
done
echo
fi
if ((run_vim_tests)); then
for vim in $(docker run --rm "$IMAGE" ls /vim-build/bin | grep '^vim' ); do
echo
echo '========================================'
echo "Running tests for $vim"
echo '========================================'
echo
set -o pipefail
docker run -a stderr "${DOCKER_FLAGS[@]}" \
"/vim-build/bin/$vim" -u test/vimrc \
"+Vader! $tests" 2>&1 | color-vader-output || EXIT=$?
set +o pipefail
done
echo
fi
if ((run_vint)); then
echo '========================================'
echo 'Running Vint to lint our code'
echo '========================================'
echo 'Vint warnings/errors follow:'
echo
set -o pipefail
docker run -a stdout "${DOCKER_FLAGS[@]}" vint -s . || EXIT=$?
set +o pipefail
echo
fi
if ((run_custom_checks)); then
echo '========================================'
echo 'Running custom checks'
echo '========================================'
echo 'Custom warnings/errors follow:'
echo
set -o pipefail
docker run -a stdout "${DOCKER_FLAGS[@]}" ./custom-checks . || EXIT=$?
set +o pipefail
echo
fi
exit $EXIT

1
test/.config/nvim/init.vim Symbolic link
View File

@ -0,0 +1 @@
../../vimrc

View File

@ -18,11 +18,13 @@ Execute(GetNextMessageID() should increment appropriately):
AssertEqual 1, ale#lsp#GetNextMessageID() AssertEqual 1, ale#lsp#GetNextMessageID()
Execute(ale#lsp#CreateMessageData() should create an appropriate message): Execute(ale#lsp#CreateMessageData() should create an appropriate message):
" 71 is the size in bytes for UTF-8, not the number of characters. " NeoVim outputs JSON with spaces, so the output is a little different.
if has('nvim')
" 79 is the size in bytes for UTF-8, not the number of characters.
AssertEqual AssertEqual
\ [ \ [
\ 1, \ 1,
\ "Content-Length: 71\r\n\r\n" \ "Content-Length: 79\r\n\r\n"
\ . '{"id": 1, "jsonrpc": "2.0", "method": "someMethod", "params": {"foo": "barÜ"}}', \ . '{"id": 1, "jsonrpc": "2.0", "method": "someMethod", "params": {"foo": "barÜ"}}',
\ ], \ ],
\ ale#lsp#CreateMessageData([0, 'someMethod', {'foo': 'barÜ'}]) \ ale#lsp#CreateMessageData([0, 'someMethod', {'foo': 'barÜ'}])
@ -30,12 +32,37 @@ Execute(ale#lsp#CreateMessageData() should create an appropriate message):
AssertEqual AssertEqual
\ [ \ [
\ 2, \ 2,
\ "Content-Length: 79\r\n\r\n"
\ . '{"id": 2, "jsonrpc": "2.0", "method": "someMethod", "params": {"foo": "barÜ"}}',
\ ],
\ ale#lsp#CreateMessageData([0, 'someMethod', {'foo': 'barÜ'}])
else
AssertEqual
\ [
\ 1,
\ "Content-Length: 71\r\n\r\n"
\ . '{"id":1,"jsonrpc":"2.0","method":"someMethod","params":{"foo":"barÜ"}}',
\ ],
\ ale#lsp#CreateMessageData([0, 'someMethod', {'foo': 'barÜ'}])
AssertEqual
\ [
\ 2,
\ "Content-Length: 71\r\n\r\n" \ "Content-Length: 71\r\n\r\n"
\ . '{"id":2,"jsonrpc":"2.0","method":"someMethod","params":{"foo":"barÜ"}}', \ . '{"id":2,"jsonrpc":"2.0","method":"someMethod","params":{"foo":"barÜ"}}',
\ ], \ ],
\ ale#lsp#CreateMessageData([0, 'someMethod', {'foo': 'barÜ'}]) \ ale#lsp#CreateMessageData([0, 'someMethod', {'foo': 'barÜ'}])
endif
Execute(ale#lsp#CreateMessageData() should create messages without params): Execute(ale#lsp#CreateMessageData() should create messages without params):
if has('nvim')
AssertEqual
\ [
\ 1,
\ "Content-Length: 56\r\n\r\n"
\ . '{"id": 1, "jsonrpc": "2.0", "method": "someOtherMethod"}',
\ ],
\ ale#lsp#CreateMessageData([0, 'someOtherMethod'])
else
AssertEqual AssertEqual
\ [ \ [
\ 1, \ 1,
@ -43,8 +70,25 @@ Execute(ale#lsp#CreateMessageData() should create messages without params):
\ . '{"id":1,"jsonrpc":"2.0","method":"someOtherMethod"}', \ . '{"id":1,"jsonrpc":"2.0","method":"someOtherMethod"}',
\ ], \ ],
\ ale#lsp#CreateMessageData([0, 'someOtherMethod']) \ ale#lsp#CreateMessageData([0, 'someOtherMethod'])
endif
Execute(ale#lsp#CreateMessageData() should create notifications): Execute(ale#lsp#CreateMessageData() should create notifications):
if has('nvim')
AssertEqual
\ [
\ 0,
\ "Content-Length: 60\r\n\r\n"
\ . '{"id": null, "jsonrpc": "2.0", "method": "someNotification"}',
\ ],
\ ale#lsp#CreateMessageData([1, 'someNotification'])
AssertEqual
\ [
\ 0,
\ "Content-Length: 86\r\n\r\n"
\ . '{"id": null, "jsonrpc": "2.0", "method": "someNotification", "params": {"foo": "bar"}}',
\ ],
\ ale#lsp#CreateMessageData([1, 'someNotification', {'foo': 'bar'}])
else
AssertEqual AssertEqual
\ [ \ [
\ 0, \ 0,
@ -59,6 +103,7 @@ Execute(ale#lsp#CreateMessageData() should create notifications):
\ . '{"id":null,"jsonrpc":"2.0","method":"someNotification","params":{"foo":"bar"}}', \ . '{"id":null,"jsonrpc":"2.0","method":"someNotification","params":{"foo":"bar"}}',
\ ], \ ],
\ ale#lsp#CreateMessageData([1, 'someNotification', {'foo': 'bar'}]) \ ale#lsp#CreateMessageData([1, 'someNotification', {'foo': 'bar'}])
endif
Execute(ale#lsp#ReadMessageData() should read single whole messages): Execute(ale#lsp#ReadMessageData() should read single whole messages):
AssertEqual AssertEqual

View File

@ -44,6 +44,7 @@ After:
sign unplace * sign unplace *
let g:ale_buffer_info = {} let g:ale_buffer_info = {}
call ale#linter#Reset()
Execute(The signs should be updated after linting is done): Execute(The signs should be updated after linting is done):
call ale#Lint() call ale#Lint()

View File

@ -1,5 +1,9 @@
Execute(The after file should have been loaded for real): Execute(The after file should have been loaded for real):
" FIXME: Fix these tests in NeoVim.
if !has('nvim')
Assert has_key(g:, 'loaded_ale_after'), 'g:loaded_ale_after was not set!'
Assert g:loaded_ale_after Assert g:loaded_ale_after
endif
Before: Before:
silent! cd /testplugin/test silent! cd /testplugin/test

View File

@ -65,7 +65,10 @@ After:
delfunction GetLastMessage delfunction GetLastMessage
mess clear " Clearing the messages breaks tests on NeoVim for some reason, but all
" we need to do for these tests is just make it so the last message isn't
" carried over between test cases.
echomsg ''
Given javascript(A Javscript file with warnings/errors): Given javascript(A Javscript file with warnings/errors):
var x = 3 var x = 3

View File

@ -44,7 +44,13 @@ Execute(History should be set when commands are run):
AssertEqual 1, len(g:history) AssertEqual 1, len(g:history)
AssertEqual sort(['status', 'exit_code', 'job_id', 'command']), sort(keys(g:history[0])) AssertEqual sort(['status', 'exit_code', 'job_id', 'command']), sort(keys(g:history[0]))
if has('nvim')
AssertEqual 'echo command history test', g:history[0].command
else
AssertEqual ['/bin/sh', '-c', 'echo command history test'], g:history[0].command AssertEqual ['/bin/sh', '-c', 'echo command history test'], g:history[0].command
endif
AssertEqual 'finished', g:history[0].status AssertEqual 'finished', g:history[0].status
AssertEqual 0, g:history[0].exit_code AssertEqual 0, g:history[0].exit_code
" The Job ID will change each time, but we can check the type. " The Job ID will change each time, but we can check the type.