RsCov.lua:
--[[ Sample: -- test/test2/t.lua : function testt() print("hello world") print("bad world") end -- test.lua : require("RsCov") require("test/test2/t") RsCov.start_cov( "test/test2/t.lua" ) testt() local dump = RsCov.dump_file("t.lua") print(dump) -- output : hello world bad world Cov:3 Uncov:6 Total:9 Pct:0.33333333333333 1 0 2 0 3 0 function testt() 4 1 print("hello world") 5 1 print("bad world") 6 1 end 7 0 8 0 9 0 ]] file_tbl = file_tbl or {} rawcoroutinecreate = rawcoroutinecreate or coroutine.create rawcoroutinewrap = rawcoroutinewrap or coroutine.wrap rawexit = rawexit or os.exit IsStarted = IsStarted or false function trim_path( name ) local s1,s2,s3 s1= name:find("/", 1, true ) while s1 do s2 = s1 s1 = name:find("/", s1+1, true ) end if s2 then s1,s3= name:find(".\", s2+1, true ) else s1,s3= name:find(".\", 1, true ) end while s1 do s2 = s3 s1 = name:find(".\", s2+1, true ) end if s2 then name = name:sub( s2+1 ) end return name end local function on_line(_, line_nr) -- get name of processed file; ignore Lua code loaded from raw strings local name = debug.getinfo(2, "S").source if not name:match("^@") then return end name = name:sub(2) name = trim_path( name ) local file = file_tbl[name] if not file then --print( "can't find :" .. name ) return end local cov = file.cov cov[line_nr] = (cov[line_nr] or 0) + 1 end function stop( ) debug.sethook() coroutine.create = rawcoroutinecreate coroutine.wrap = rawcoroutinewrap os.exit = rawexit IsStarted = false file_tbl = {} end function start_cov( filename ) local ret = "Ok" if filename then ret = add_cov_file( filename ) end if not IsStarted then debug.sethook(on_line, "l") IsStarted = true coroutine.create = function(...) local co = rawcoroutinecreate(...) debug.sethook(co, on_line, "l") return co end coroutine.wrap = function(...) local co = rawcoroutinecreate(...) debug.sethook(co, on_line, "l") return function() local r = { coroutine.resume(co) } if not r[1] then error(r[2]) end return unpack(r, 2) end end os.exit = function(...) on_exit() rawexit(...) end end return ret end function clean( name ) if type(name) == "table" then local ret = "fail with : " local fail = false for i,v in pairs( name ) do if clean( v ) ~= "Ok" then ret = ret .. v .. "," fail = true end end if fail then return ret else return "Ok" end end if type(name) ~= "string" then return "clean file fail, need a string argument." end name = trim_path( name ) local file = file_tbl[ name ] file.cov = {} return "Ok" end function add_cov_file( name ) if type(name) == "table" then local ret = "fail with : " local fail = false for i,v in pairs( name ) do if add_cov_file( v ) ~= "Ok" then ret = ret .. v .. "," fail = true end end if fail then return ret else return "Ok" end end if type(name) ~= "string" then return "add coverage file fail, need a string argument." end local file = {} for line in io.lines(name) do table.insert( file, line ) end local file_len = #file if file_len == 0 then return "read coverage file fail for " .. name end name = trim_path( name ) file_tbl[ name ] = file file.cov = {} --print(name) --printTable( file ) return "Ok" end function dump_file( name ) name = trim_path( name ) local file = file_tbl[name] if not file then return "file is not in record" end local info = "" local has_cov = 0 local un_cov = 0 local cov = file.cov local show = {} local has_run = false for k,v in ipairs( file ) do local run = cov[ k ] or 0 if run == 0 then show[k] = true show[k-1] = true show[k+1] = true --[[ show[k-2] = true show[k-3] = true show[k+2] = true show[k+3] = true ]] else has_run = true show[k] = false end end if not has_run then return "file has not been executed." end --printTable( show) for k, v in ipairs( file ) do local run = cov[ k ] or 0 if run == 0 then if v ~= "" then un_cov = un_cov+1 end else has_cov = has_cov +1 end if show[k] then info = info .. k .. " " .. run .. " " .. v .. "\n" else --info = info .. k .. " " .. run .. " " .. "[classified]..." .. "\n" end end local total = un_cov + has_cov local pct = has_cov/total return "Cov:" .. tostring(has_cov) .. " Uncov:" .. tostring(un_cov) .. " Total:" .. tostring(total) .. " Pct:" .. tostring(pct) .. "\n" .. info end --[[ Sample: -- test/test2/t.lua : func