summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Silverstone <dsilvers@digital-scurf.org>2017-03-04 16:08:27 +0000
committerDaniel Silverstone <dsilvers@digital-scurf.org>2017-03-04 17:35:18 +0000
commitb609d07be3b37f81f5c05ae56bd427d16bb6f5c9 (patch)
treec38a7b0c0bd126e989cb7582a1f9fbd30333adb5
parentf2f5b4e6229532f3ba69e9f32bc3305e37b20f4c (diff)
downloadgitano-b609d07be3b37f81f5c05ae56bd427d16bb6f5c9.tar.gz
adds support for coverage testing
-rw-r--r--.editorconfig2
-rw-r--r--.gitignore4
-rw-r--r--.luacov22
-rw-r--r--Makefile66
-rw-r--r--lib/gitano/coverage.lua.in52
-rw-r--r--utils/install-lua-bin38
-rw-r--r--utils/merge-luacov-stats66
7 files changed, 235 insertions, 15 deletions
diff --git a/.editorconfig b/.editorconfig
index 0dc0e75..b0bee21 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -11,7 +11,7 @@ charset = utf-8
trim_trailing_whitespace = true
# Lua code should be space indented, to 3 spaces
-[{*.lua,bin/*.in,testing/gitano-test-tool.in,utils/install-lua-bin}]
+[{*.lua,bin/*.in,testing/gitano-test-tool.in,utils/install-lua-bin,utils/merge-luacov-stats,.luacov}]
indent_style = space
indent_size = 3
diff --git a/.gitignore b/.gitignore
index 03c55e9..d2172e5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,7 @@
*~
run
t
+.coverage
+luacov.stats.out
+luacov.report.out
+lib/gitano/coverage.lua
diff --git a/.luacov b/.luacov
new file mode 100644
index 0000000..ffc7ab3
--- /dev/null
+++ b/.luacov
@@ -0,0 +1,22 @@
+-- -*- Lua -*-
+return {
+ statsfile = "luacov.stats.out",
+ reportfile = "luacov.report.out",
+ tick = false,
+ savestepsize = 100,
+ runreport = false,
+ deletestats = false,
+ codefromstrings = false,
+ include = { },
+ exclude = {
+ "^/usr/share",
+ "%.conf$",
+ "%.clod$",
+ "clod%-config", "^hooks/", "supple%-transfer",
+ "lang/[^/]+$",
+ "lib/gitano$",
+ "plugins/demo$",
+ "gitano/coverage$",
+ },
+ modules = {},
+}
diff --git a/Makefile b/Makefile
index 08ad6a5..c85383a 100644
--- a/Makefile
+++ b/Makefile
@@ -86,12 +86,24 @@ TESTS := $(patsubst %,testing/%.yarn,$(TESTS))
GEN_BIN := utils/install-lua-bin
RUN_GEN_BIN := $(LUA) $(GEN_BIN) $(LUA)
+
+COVERAGE := no
+
+ifeq ($(COVERAGE),yes)
+define GEN_LOCAL_BIN
+
+$(RUN_GEN_BIN) $(shell pwd) $(shell pwd)/bin $(shell pwd)/lib $(shell pwd)/plugins $1 $2 $(shell pwd)/extras/luacov/src $(shell pwd)/.coverage/
+chmod 755 $2
+
+endef
+else
define GEN_LOCAL_BIN
$(RUN_GEN_BIN) $(shell pwd) $(shell pwd)/bin $(shell pwd)/lib $(shell pwd)/plugins $1 $2
chmod 755 $2
endef
+endif
define GEN_INSTALL_BIN
@@ -113,23 +125,51 @@ install -m 644 $1 $2
endef
-local: $(LOCAL_BINS)
- $(LUAC) -p $(LOCAL_BINS)
+define GEN_LOCAL_MOD
-clean:
- @echo "CLEAN: local binaries"
- @$(RM) $(LOCAL_BINS)
+$(RUN_GEN_BIN) $(shell pwd) $(shell pwd)/bin $(shell pwd)/lib $(shell pwd)/plugins $1 $2
+
+endef
+
+LOCAL_MODS := lib/gitano/coverage.lua
+
+local: $(LOCAL_BINS) $(LOCAL_MODS)
+ @$(LUAC) -p $(LOCAL_BINS) $(LOCAL_MODS)
+ @mkdir -p .coverage
+ifeq ($(COVERAGE),yes)
+ @echo NOTE: Coverage gathering enabled
+ @if ! test -r extras/luacov/src/luacov; then \
+ echo "CANNOT COVERAGE TEST, LUACOV MODULE NOT AVAILABLE"; \
+ echo "Please run: git submodule init && git submodule update"; \
+ fi
+else
+ @echo NOTE: Coverage gathering is not enabled
+endif
+
+clean: cleanbins
+ @echo "CLEAN: coverage stats and reports"
+ @$(RM) -r .coverage luacov.stats.out luacov.report.out
+
+cleanbins:
+ @echo "CLEAN: local binaries and modules"
+ @$(RM) $(LOCAL_BINS) $(LOCAL_MODS)
@echo "CLEAN: test binaries"
@$(RM) $(TEST_BINS)
distclean: clean
@find . -name "*~" -delete
-bin/%: bin/%.in $(GEN_BIN)
- $(call GEN_LOCAL_BIN,$<,$@)
+bin/%: bin/%.in $(GEN_BIN) FORCE
+ @$(call GEN_LOCAL_BIN,$<,$@)
-testing/%: testing/%.in $(GEN_BIN)
- $(call GEN_LOCAL_BIN,$<,$@)
+testing/%: testing/%.in $(GEN_BIN) FORCE
+ @$(call GEN_LOCAL_BIN,$<,$@)
+
+lib/gitano/%.lua: lib/gitano/%.lua.in $(GEN_BIN) FORCE
+ @$(call GEN_LOCAL_MOD,$<,$@)
+
+FORCE:
+.PHONY: FORCE
install: install-bins install-lib-bins install-mods install-skel install-man install-plugins install-lang
@@ -242,3 +282,11 @@ testing/%: testing/%.in $(GEN_BIN)
$(call GEN_LOCAL_BIN,$<,$@)
check: test
+
+coverage-report:
+ @echo "COVERAGE: Merge stats..."
+ @env LUA_PATH="$(shell pwd)/extras/luacov/src/?.lua;;" $(LUA) utils/merge-luacov-stats .coverage/luacov.stats-*.out
+ @echo "COVERAGE: Generate report..."
+ @env LUA_PATH="$(shell pwd)/extras/luacov/src/?.lua;;" $(LUA) extras/luacov/src/bin/luacov
+ @echo "COVERAGE: Summary:"
+ @sed '0,/^Summary/d' < luacov.report.out | tail -n +2 | sed -e's/^/COVERAGE: /'
diff --git a/lib/gitano/coverage.lua.in b/lib/gitano/coverage.lua.in
new file mode 100644
index 0000000..65d7682
--- /dev/null
+++ b/lib/gitano/coverage.lua.in
@@ -0,0 +1,52 @@
+-- gitano.coverage
+--
+-- Coverage generation for when running Gitano under test.
+-- NOTE: Not to be installed as part of Gitano, not to be loaded from the
+-- top level gitano module
+--
+-- Copyright 2017 Daniel Silverstone <dsilvers@digital-scurf.org>
+-- All rights reserved.
+--
+-- Redistribution and use in source and binary forms, with or without
+-- modification, are permitted provided that the following conditions
+-- are met:
+-- 1. Redistributions of source code must retain the above copyright
+-- notice, this list of conditions and the following disclaimer.
+-- 2. Redistributions in binary form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+-- 3. Neither the name of the author nor the names of their contributors
+-- may be used to endorse or promote products derived from this software
+-- without specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+-- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+-- ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+-- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+-- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+-- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+-- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+-- SUCH DAMAGE.
+--
+
+local ok, runner = pcall(require, "luacov.runner")
+
+local luxio = require("luxio")
+
+local conf = assert(loadfile("@@.luacov@@"))()
+
+local function begin(basepath, part)
+ if not ok then return end
+ basepath = basepath or "./"
+ local pidstr = (".%d"):format(luxio.getpid())
+ part = (part or "general") .. pidstr
+ conf.statsfile = basepath .. "luacov.stats-" .. part .. ".out"
+ runner.init(conf)
+end
+
+return {
+ begin = begin,
+}
diff --git a/utils/install-lua-bin b/utils/install-lua-bin
index 41a7bd2..1f27a49 100644
--- a/utils/install-lua-bin
+++ b/utils/install-lua-bin
@@ -27,7 +27,9 @@
-- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-- SUCH DAMAGE.
-local lua_bin, inst_share_path, inst_bin_path, inst_mod_path, inst_plugin_path, input_name, output_name = ...
+local lua_bin, inst_share_path, inst_bin_path, inst_mod_path, inst_plugin_path, input_name, output_name, coverage_path, report_path = ...
+
+local luxio = require("luxio")
local input_fh = assert(io.open(input_name, "r"))
local output_fh = assert(io.open(output_name, "w"))
@@ -39,6 +41,22 @@ if not inst_mod_path:match("%?") then
inst_mod_path = inst_mod_path:gsub("/+", "/")
end
+if coverage_path and coverage_path == "" then
+ coverage_path = nil
+end
+
+if coverage_path and not coverage_path:match("%?") then
+ coverage_path = coverage_path .. "/?.lua"
+ coverage_path = coverage_path:gsub("/+", "/")
+end
+
+local coverage_part
+if coverage_path then
+ -- We are generating coverage, the part is the leafname of the
+ -- output binary
+ coverage_part = output_name:gsub("^.+/", "")
+end
+
local mod_path_present = false
for path_elem in package.path:gmatch("([^;]+)") do
if path_elem == inst_mod_path then
@@ -65,12 +83,20 @@ while line do
elseif token == "GITANO_LUA_PATH" then
if not mod_path_present then
output_fh:write(("package.path = ('%%s;%%s'):" ..
- "format(%q, package.path)" ..
- "\n"):format(inst_mod_path))
+ "format(%q, package.path)"
+ ):format(inst_mod_path))
else
- output_fh:write("-- Gitano modules installed into " ..
- inst_mod_path .. "\n")
+ output_fh:write("--[[Gitano modules installed into " ..
+ inst_mod_path .. "]]")
+ end
+ if coverage_path then
+ output_fh:write((" package.path = ('%%s;%%s'):" ..
+ "format(%q, package.path)"
+ ):format(coverage_path))
+ output_fh:write((" require('gitano.coverage').begin(%q, %q)"
+ ):format(report_path, coverage_part))
end
+ output_fh:write("\n")
elseif token == "GITANO_BIN_PATH" then
output_fh:write(("gitano.config.lib_bin_path(%q)\n"):format(inst_bin_path))
elseif token == "GITANO_SHARE_PATH" then
@@ -82,6 +108,8 @@ while line do
else
output_fh:write("-- Unknown token: " .. token .. "\n")
end
+ elseif line:match("@@%.luacov@@") then
+ output_fh:write(line:gsub("@@%.luacov@@", luxio.getcwd() .. "/.luacov") .. "\n")
else
output_fh:write(line .. "\n")
end
diff --git a/utils/merge-luacov-stats b/utils/merge-luacov-stats
new file mode 100644
index 0000000..f4b28ae
--- /dev/null
+++ b/utils/merge-luacov-stats
@@ -0,0 +1,66 @@
+-- Run this explicitly through -*- Lua -*-
+
+-- Copyright 2017 Daniel Silverstone <dsilvers@digital-scurf.org>
+-- All rights reserved.
+--
+-- Redistribution and use in source and binary forms, with or without
+-- modification, are permitted provided that the following conditions
+-- are met:
+-- 1. Redistributions of source code must retain the above copyright
+-- notice, this list of conditions and the following disclaimer.
+-- 2. Redistributions in binary form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+-- 3. Neither the name of the author nor the names of their contributors
+-- may be used to endorse or promote products derived from this software
+-- without specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+-- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+-- ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+-- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+-- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+-- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+-- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+-- SUCH DAMAGE.
+
+local infiles = {...}
+
+local stats = require("luacov.stats")
+
+-- Step 1, merge all the coverage files together into a single one...
+
+local merged = {}
+
+function merge_data(fname)
+ local subdata = stats.load(fname)
+ for fname, fdat in pairs(subdata) do
+ if not merged[fname] then
+ merged[fname] = fdat
+ else
+ for i = 1, fdat.max do
+ merged[fname][i] = (merged[fname][i] or 0) + (fdat[i] or 0)
+ end
+ end
+ end
+end
+
+local percent = 0
+for i = 1, #infiles do
+ merge_data(infiles[i])
+ local newpercent = math.floor((i*100) / #infiles)
+ if (newpercent - percent > 0) or (newpercent == 100) then
+ io.stdout:write(("COVERAGE: %3d%% merged.\r"):format(newpercent))
+ percent = newpercent
+ io.stdout:flush();
+ end
+end
+io.stdout:write("\n");
+
+-- Step 2, write it all out
+
+print("Saving merged stats")
+stats.save("luacov.stats.out", merged)