From b823dd4ed4d69db1ba8a24172dabf250e6b16c4f Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Sat, 6 Feb 2016 15:23:28 +0100 Subject: [PATCH 1/3] Add code coverage support This uses coveralls.io and integrates the collection of coverage information with Travis. Signed-off-by: Uli Schlachter --- .luacov | 26 ++++++++++++++++++++++++++ .travis.yml | 8 +++++++- CMakeLists.txt | 8 ++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 .luacov diff --git a/.luacov b/.luacov new file mode 100644 index 000000000..b236077e1 --- /dev/null +++ b/.luacov @@ -0,0 +1,26 @@ +-- Configuration file for LuaCov + +-- This variable is set externally +local build = os.getenv("BUILD_DIRECTORY") or error("$BUILD_DIRECTORY not set") +local lib_dir = build .. "lib/" + +local function escape_pattern(str) + return string.gsub(str, "%W", "%%%1") +end + +return { + statsfile = build .. "luacov.stats.out", + + include = { + escape_pattern(lib_dir) .. ".+", + }, + + -- configuration for luacov-coveralls reporter + coveralls = { + pathcorrect = { + { escape_pattern(lib_dir), "lib/"}, + }, + }, +} + +-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/.travis.yml b/.travis.yml index f973840b5..01d5c1e57 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,7 @@ env: matrix: # Note: luarocks does not work with Lua 5.0. - LUA=5.1 LGIVER= LUANAME=lua5.1 - - LUA=5.2 LGIVER= LUANAME=lua5.2 BUILD_APIDOC=true + - LUA=5.2 LGIVER= LUANAME=lua5.2 BUILD_APIDOC=true DO_COVERAGE=true - LUA=5.2 LGIVER=0.7.1 LUANAME=lua5.2 # luajit: requires --lua-suffix=jit-2.0.0-beta9 in Ubuntu precise. # Later versions seem to provide a `luajit` symlink, so `jit` would be enough. @@ -73,6 +73,9 @@ install: - travis_retry sudo luarocks install ldoc - travis_retry sudo luarocks install lua-discount + # Instal luacov-coveralls for code coverage testing. + - if [ "$DO_COVERAGE" = "true" ]; then sudo luarocks install luacov-coveralls; fi + # Determine custom version. - export AWESOME_VERSION="${TRAVIS_BRANCH}-g$(git rev-parse --short HEAD)" - 'if [ "$TRAVIS_PULL_REQUEST" != false ]; then AWESOME_VERSION="${AWESOME_VERSION}-PR${TRAVIS_PULL_REQUEST}"; fi' @@ -80,7 +83,10 @@ install: script: - export CMAKE_ARGS="-DLUA_LIBRARY=${LUALIBRARY} -DLUA_INCLUDE_DIR=${LUAINCLUDE} -D OVERRIDE_VERSION=$AWESOME_VERSION" - make && sudo env PATH=$PATH make install && awesome --version && make check + - if [ "$DO_COVERAGE" = "true" ]; then make check-coverage; fi after_success: # Push updated API docs for relevant branches, e.g. non-PRs builds on master. - if [ "$BUILD_APIDOC" = "true" ]; then build-utils/travis-apidoc.sh; fi + # Push code coverage information + - if [ "$DO_COVERAGE" = "true" ]; then BUILD_DIRECTORY="$(pwd)/$(readlink build)/" luacov-coveralls --verbose --merge; fi diff --git a/CMakeLists.txt b/CMakeLists.txt index a1fad8757..80f9d5dcb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -368,6 +368,14 @@ if(BUSTED_EXECUTABLE) WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMENT "Running unit tests" VERBATIM) + add_custom_target(check-coverage + "BUILD_DIRECTORY=${CMAKE_BINARY_DIR}/" + ${BUSTED_EXECUTABLE} "--helper=${CMAKE_SOURCE_DIR}/spec/preload.lua" + "--lpath=${CMAKE_BINARY_DIR}/lib/?.lua;${CMAKE_BINARY_DIR}/lib/?/init.lua;spec/?.lua" + "--coverage" + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + COMMENT "Running unit tests under LuaCov" + VERBATIM) endif() add_custom_target(check-integration "${CMAKE_SOURCE_DIR}/tests/run.sh" From 9e05ff63ce99145cd1215732de86e6c9c1b568b0 Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Sat, 6 Feb 2016 17:18:23 +0100 Subject: [PATCH 2/3] Code coverage: Also consider functional tests Lots of our code depends on the C API and thus can only be tested when that is available. Hence, it makes sense to also run the functional tests under LuaCov. Signed-off-by: Uli Schlachter --- .luacov | 4 ++++ .travis.yml | 7 ++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/.luacov b/.luacov index b236077e1..5f7f3eb72 100644 --- a/.luacov +++ b/.luacov @@ -13,6 +13,10 @@ return { include = { escape_pattern(lib_dir) .. ".+", + + -- For things already having the correct path + -- (happens with integration tests) + "^lib/", }, -- configuration for luacov-coveralls reporter diff --git a/.travis.yml b/.travis.yml index 01d5c1e57..de5484bcb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -83,7 +83,12 @@ install: script: - export CMAKE_ARGS="-DLUA_LIBRARY=${LUALIBRARY} -DLUA_INCLUDE_DIR=${LUAINCLUDE} -D OVERRIDE_VERSION=$AWESOME_VERSION" - make && sudo env PATH=$PATH make install && awesome --version && make check - - if [ "$DO_COVERAGE" = "true" ]; then make check-coverage; fi + - | + if [ "$DO_COVERAGE" = "true" ]; then + make check-coverage || exit 1; + sed -i "1 i\\require('luacov.runner')('"$PWD"/.luacov')" build/awesomerc.lua || exit 1 + BUILD_DIRECTORY="" tests/run.sh || exit 1 + fi after_success: # Push updated API docs for relevant branches, e.g. non-PRs builds on master. From 432908dd26cbfcd62c39a756b43038136bba9573 Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Fri, 12 Feb 2016 09:23:41 +0100 Subject: [PATCH 3/3] Fix test-leak-client.lua under LuaCov Both the test runner and the wibox use gears.timer.delayed_call(). The test runner uses this to call steps and the wibox uses it to trigger redraws. When running under LuaCov, the Lua code becomes slow enough that the wibox didn't redraw yet when the leak check is run. This causes the check to fail, because the client is still referenced by the tasklist and thus cannot be garbage collected. Fix this by waiting one more iteration before running the leak check. Signed-off-by: Uli Schlachter --- tests/test-leak-client.lua | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/test-leak-client.lua b/tests/test-leak-client.lua index 205e48248..c70bf3699 100644 --- a/tests/test-leak-client.lua +++ b/tests/test-leak-client.lua @@ -46,6 +46,7 @@ collectgarbage("stop") -- The first iteration starts xterm, the second keeps a weak reference to it and -- closes it and the last one checks that the client object is GC'able. local objs = nil +local second_call = false local steps = { function(count) if count == 1 then @@ -56,6 +57,10 @@ local steps = { objs = setmetatable({ c }, { __mode = "v" }) c:kill() end + elseif not second_call then + -- Wait for one iteration so that gears.timer handles other delayed + -- calls (= the tasklist updates) + second_call = true else assert(#objs == 1)